题很简单:给两个操作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 ",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; }