题目连接:http://poj.org/problem?id=3667
题意:1 a:询问是不是有连续长度为a的空房间,有的话住进最左边
2 a b:将[a,a+b-1]的房间清空
线段树操作:update:区间替换 query:询问满足条件的最左断点
#include<iostream> #include<cstdio> #include<cstring> #include<algorithm> #define LL long long #define M 1000000000 #define maxn 55555 #define lson l,m,rt<<1 #define rson m+1,r,rt<<1|1 using namespace std; int lsum[maxn<<2],rsum[maxn<<2],sum[maxn<<2]; int col[maxn<<2]; void PushDown(int rt,int m) { if(col[rt]!=-1) { col[rt<<1]=col[rt<<1|1]=col[rt]; sum[rt<<1]=lsum[rt<<1]=rsum[rt<<1]=col[rt]?0:m-(m>>1); sum[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]; sum[rt]=max((lsum[rt<<1|1]+rsum[rt<<1]),max(sum[rt<<1],sum[rt<<1|1])); } void build(int l,int r,int rt) { col[rt]=-1; sum[rt]=lsum[rt]=rsum[rt]=r-l+1; if(l==r)return; int m=(r+l)>>1; build(lson); build(rson); } void update(int L,int R,int c,int l,int r,int rt) { if(L<=l&&r<=R) { sum[rt]=lsum[rt]=rsum[rt]=c?0:r-l+1; col[rt]=c; return; } PushDown(rt,r-l+1); int m=(r+l)>>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 w,int l,int r,int rt) { if(l==r)return l; PushDown(rt,r-l+1); int m=(r+l)>>1; if(sum[rt<<1]>=w)return query(w,lson); else if(rsum[rt<<1]+lsum[rt<<1|1]>=w)return m-rsum[rt<<1]+1; else return query(w,rson); } int main() { int n,m; while(scanf("%d%d",&n,&m)>0) { build(1,n,1); while(m--) { int a,b,op; scanf("%d",&op); if(op==1) { scanf("%d",&a); if(sum[1]<a)puts("0"); else { int ans=query(a,1,n,1); printf("%d\n",ans); update(ans,ans+a-1,1,1,n,1); } } else { scanf("%d%d",&a,&b); update(a,a+b-1,0,1,n,1); } } } }