poj3667---Hotel 线段树区间合并,区间更新
2014-09-28 16:39
288 查看
题意:有N个房间,M次操作。有两种操作(1)"1 a",表示找到连续的长度为a的空房间,如果有多解,优先左边的,即表示入住。(2)"2 b len",把起点为b长度的len的房间清空,即退房。三个数组分别记录 lsum区间左值 rsum区间右值 sum区间最大值。
#include <set> #include <map> #include <cmath> #include <ctime> #include <queue> #include <stack> #include <cctype> #include <cstdio> #include <string> #include <vector> #include <cstdlib> #include <cstring> #include <iostream> #include <algorithm> using namespace std; typedef unsigned long long ull; typedef long long ll; const int inf = 0x3f3f3f3f; const double eps = 1e-8; template <class T> inline bool scan_d(T &ret) { char c; int sgn; if(c=getchar(),c==EOF) return 0; while(c!='-'&&(c<'0'||c>'9')) c=getchar(); sgn=(c=='-')?-1:1; ret=(c=='-')?0:(c-'0'); while(c=getchar(),c>='0'&&c<='9') ret=ret*10+(c-'0'); ret*=sgn; return 1; } const int maxn = 5e4+10; int lv[maxn<<2],rv[maxn<<2], setv[maxn<<2]; //lv,rv数组可有可无,lsum rsum数组已经包含了他们的意义。 int lsum[maxn<<2],rsum[maxn<<2],sum[maxn<<2]; void push_up(int l,int r,int pos) { lv[pos] = lv[pos<<1]; rv[pos] = rv[pos<<1|1]; lsum[pos] = lsum[pos<<1]; rsum[pos] = rsum[pos<<1|1]; sum[pos] = max(sum[pos<<1],sum[pos<<1|1]); sum[pos] = max(sum[pos],rsum[pos<<1]+lsum[pos<<1|1]); int mid = (l + r) >> 1; if (rv[pos<<1] ==lv[pos<<1|1] && !rv[pos<<1]) { if (lsum[pos<<1] == mid - l + 1) lsum[pos] += lsum[pos<<1|1]; if (rsum[pos<<1|1] == r - mid) rsum[pos] += rsum[pos<<1]; sum[pos] = max(sum[pos],rsum[pos<<1]+lsum[pos<<1|1]); } } void push_down(int l,int r,int pos) { if (~setv[pos]) { int mid = (l + r) >> 1; setv[pos<<1] = setv[pos<<1|1] = setv[pos]; lv[pos<<1] = setv[pos]; lv[pos<<1|1] = setv[pos]; rv[pos<<1] = setv[pos]; rv[pos<<1|1] = setv[pos]; lsum[pos<<1] = (setv[pos] ? 0 : (mid-l+1)); rsum[pos<<1] = (setv[pos] ? 0 : (mid-l+1)); lsum[pos<<1|1] = (setv[pos] ? 0 : (r-mid)); rsum[pos<<1|1] = (setv[pos] ? 0 : (r-mid)); sum[pos<<1] = (setv[pos] ? 0 : (mid-l+1)); sum[pos<<1|1] = (setv[pos] ? 0 : (r-mid)); setv[pos] = -1; } } void build (int l,int r,int pos) { if (l == r) { rv[pos] = lv[pos] = 0; sum[pos] = lsum[pos] = rsum[pos] = 1; return; } int mid = (l + r) >> 1; build(l,mid,pos<<1); build(mid+1,r,pos<<1|1); push_up(l,r,pos); } void update(int l,int r,int pos,int ua,int ub,int val) { if (ua <= l && ub >= r) { setv[pos] = val; lv[pos] = val; rv[pos] = val; lsum[pos] = (val ? 0 : (r-l+1)); rsum[pos] = (val ? 0 : (r-l+1)); sum[pos] = (val ? 0 : (r-l+1)); return; } int mid = (l + r) >> 1; push_down(l,r,pos); if (ua <= mid) update(l,mid,pos<<1,ua,ub,val); if (ub > mid) update(mid+1,r,pos<<1|1,ua,ub,val); push_up(l,r,pos); } int query(int l,int r,int pos,int x) { if (lsum[pos] >= x) { return l; } int mid = (l + r) >> 1; push_down(l,r,pos); if (sum[pos<<1] >= x) return query(l,mid,pos<<1,x); /*else if (rsum[pos<<1]&&rsum[pos<<1] + lsum[pos<<1|1] >= x) //注释部分是错误的,,看起来很像但是不一样的 return query(l,mid,pos<<1,rsum[pos<<1]);*/ else if (rsum[pos<<1] + lsum[pos<<1|1] >= x) return mid+1-rsum[pos<<1]; else return query(mid+1,r,pos<<1|1,x); } int main(void) { #ifndef ONLINE_JUDGE freopen("in.txt","r",stdin); #endif int n,q; while (~scanf ("%d%d",&n,&q)) { build(1,n,1); memset(setv,-1,sizeof(setv)); for (int i = 0; i < q; i++) { int op,x,y; scanf ("%d",&op); if (op == 1) { scanf ("%d",&x); if (sum[1] < x) { printf("0\n"); continue; } int p = query(1,n,1,x); printf("%d\n",p); update(1,n,1,p,p+x-1,1); } else { scanf ("%d%d",&x,&y); update(1,n,1,x,y+x-1,0); } } } return 0; }
相关文章推荐
- [线段树]poj3667 Hotel(区间合并、更新、延迟/懒惰标记
- poj3667 Hotel 线段树延迟更新 区间合并
- 线段树 区间更新(hdu1698) 区间合并(poj3667)
- [POJ3667]Hotel(线段树,区间合并)
- poj 3667 Hotel(线段树区间更新合并)
- POJ3667——线段树区间合并(未搞透)——Hotel
- poj3667 Hotel 线段树 区间合并
- Poj 3667 - Hotel 线段树-- 区间更新 区间合并 区间查询
- poj3667 Hotel (线段树区间合并)
- poj3667 Hotel (线段树+区间合并)
- poj3667 Hotel (线段树--区间合并)转自网络
- POJ3667-Hotel-线段树区间合并(模板)
- poj3667 hotel(线段树区间合并)
- poj3667-Hotel 线段树区间合并
- POJ 3667 Hotel 线段树 区间更新 区间合并
- poj3667 Hotel (线段树--区间合并)转自网络【2】
- 【线段树区间合并】POJ3667-Hotel
- [POJ3667]Hotel(线段树,区间合并,重写)
- POJ3667:Hotel(线段树区间合并)
- Tunnel Warfare HDU - 1540 单点更新 区间合并 线段树