poj 3667 Hotel 区间合并

1 a:询问有没有连续长度为a的空位置,插进最左边

2 a b :【a,a+b-1】区间清空

结点记录的信息:

1:区间内最长的连续空位(msum)

2:从当前区间的最左端开始的连续空位长度(lsum)

3:从当前区间的最右端开始的连续空位长度(往左边数)(rsum)

区间的最值就是max(左右子节点最长连续空位的最大值,lsum【rt<<1|1】+rsum[rt<<1])

其他就基本上和一般的成段更新,懒惰标记没什么区别了

View Code
#include<cstdio>
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1
#define max(a,b) (a)>(b)?(a):(b)
const int maxn = 50010;
int msum[maxn<<2],lsum[maxn<<2],rsum[maxn<<2],col[maxn<<2];
void pushdown(int rt,int m){
if(col[rt]!=-1){
col[rt<<1]=col[rt<<1|1]=col[rt];
msum[rt<<1]=lsum[rt<<1]=rsum[rt<<1]=col[rt] ? 0:m-(m>>1);
msum[rt<<1|1]=lsum[rt<<1|1]=rsum[rt<<1|1]=col[rt] ? 0 : (m>>1);
col[rt]=-1;
}
}
void pushup(int rt,int m){
lsum[rt]=lsum[rt<<1];
rsum[rt]=rsum[rt<<1|1];
if(lsum[rt]==m-(m>>1)) lsum[rt]+=lsum[rt<<1|1];
if(rsum[rt]==(m>>1)) rsum[rt]+=rsum[rt<<1];
msum[rt]=max(lsum[rt<<1|1]+rsum[rt<<1],max(msum[rt<<1],msum[rt<<1|1]));
}
void build(int l,int r,int rt){
msum[rt]=lsum[rt]=rsum[rt]=r-l+1;
col[rt]=-1;
if(l==r) return ;
int m=(l+r)>>1;
build(lson);
build(rson);
}
void update(int L,int R,int c,int l,int r,int rt){
if(L<=l&&r<=R){
msum[rt]=lsum[rt]=rsum[rt] = c ? 0 : r-l+1;
col[rt]=c;
return ;
}
pushdown(rt,r-l+1);
int m=(l+r)>>1;
if(L<=m) update(L,R,c,lson);
if(R>m) update(L,R,c,rson);
pushup(rt,r-l+1);
}
int query(int len,int l,int r,int rt){
if(l==r) return l;
pushdown(rt,r-l+1);
int m=(l+r)>>1;
if(msum[rt<<1]>=len) return query(len,lson);
else if(lsum[rt<<1|1]+rsum[rt<<1]>=len) return m-rsum[rt<<1]+1;
else return query(len,rson);
}
int main(){
int n,m,flag,a,b,c;
while(scanf("%d%d",&n,&m)!=EOF){
build(1,n,1);
while(m--){
scanf("%d",&flag);
if(flag==1){
scanf("%d",&a);
if(msum[1]<a) printf("0\n");
else {
int id=query(a,1,n,1);printf("%d\n",id);
update(id,id+a-1,1,1,n,1);
}
}
else {
scanf("%d%d",&a,&b);
update(a,a+b-1,0,1,n,1);
}
}
}
return 0;
}



posted @ 2012-01-14 04:30  Because Of You  Views(340)  Comments(0Edit  收藏  举报