题很简单:给两个操作1:查找最左边的a个空余块并填满
2:把从第a个开始的连续b个块置空
线段树维护左连续,右连续,最大连续,lazy-tag即可,query函数值得学习
#include<iostream> #include<cstring> #include<cstdio> #include<algorithm> using namespace std; #define maxn 500005 #define lson l,m,rt<<1 #define rson m+1,r,rt<<1|1 int lmx[maxn<<2],rmx[maxn<<2],mx[maxn<<2],flag[maxn<<2];inline void set0(int l,int r,int rt){lmx[rt]=rmx[rt]=mx[rt]=r-l+1;flag[rt]=0; } inline void set1(int l,int r,int rt){lmx[rt]=rmx[rt]=mx[rt]=0;flag[rt]=1; } inline void pushup(int l,int r,int rt){lmx[rt]=lmx[rt<<1];rmx[rt]=rmx[rt<<1|1];mx[rt]=max(mx[rt<<1],mx[rt<<1|1]);int m=l+r>>1;if(lmx[rt<<1]==m-l+1) lmx[rt]+=lmx[rt<<1|1];if(rmx[rt<<1|1]==r-m) rmx[rt]+=rmx[rt<<1];if(rmx[rt<<1]&&lmx[rt<<1|1]) mx[rt]=max(mx[rt],rmx[rt<<1]+lmx[rt<<1|1]); } inline void pushdown(int l,int r,int rt){if(flag[rt]>=0){int m=l+r>>1; flag[rt<<1]=flag[rt<<1|1]=flag[rt];if(flag[rt]==0){set0(lson);set0(rson);}else if(flag[rt]==1){set1(lson);set1(rson);}flag[rt]=-1;} } void build(int l,int r,int rt){if(l==r){lmx[rt]=rmx[rt]=mx[rt]=1;flag[rt]=-1;return;}int m=l+r>>1;build(lson);build(rson);pushup(l,r,rt); } void update(int L,int R,int op,int l,int r,int rt){if(L<=l && R>=r){if(op==0) set0(l,r,rt);if(op==1) set1(l,r,rt);return;}pushdown(l,r,rt);int m=l+r>>1;if(L<=m) update(L,R,op,lson);if(R>m)update(L,R,op,rson);pushup(l,r,rt); } //cnt要么在左儿子,要么在中间合并块,要么在右子树 int query(int cnt,int l,int r,int rt){if(l==r)return l;pushdown(l,r,rt);int m=l+r>>1;if(cnt<=mx[rt<<1])return query(cnt,lson);else if(cnt<=rmx[rt<<1]+lmx[rt<<1|1])return m-rmx[rt<<1]+1;else return query(cnt,rson); } int main(){int n,m;while(scanf("%d%d",&n,&m)==2){build(1,n,1);int a,b,op;while(m--){scanf("%d",&op);if(op==1){scanf("%d",&a);if(mx[1]<a){puts("0");continue;}int tmp=query(a,1,n,1);printf("%d\n",tmp);update(tmp,tmp+a-1,1,1,n,1);}else if(op==2){scanf("%d%d",&a,&b);update(a,a+b-1,0,1,n,1);}}}return 0; }