题意:询问区间最长连续空串
/* 用线段树维护区间最长连续左空串和右空串 */ #include<cstdio> #include<iostream> #define N 50010 using namespace std; int sum[N*4],lsum[N*4],rsum[N*4],cover[N*4],n,m; void push_up(int k,int l,int r){ int mid=l+r>>1; sum[k]=max(max(sum[k*2],sum[k*2+1]),rsum[k*2]+lsum[k*2+1]); lsum[k]=lsum[k*2]; if(lsum[k*2]==mid-l+1) lsum[k]+=lsum[k*2+1]; rsum[k]=rsum[k*2+1]; if(rsum[k*2+1]==r-mid) rsum[k]+=rsum[k*2]; } void push_down(int k,int l,int r){ if(!cover[k]) return; int mid=l+r>>1; if(cover[k]==-1){ lsum[k*2]=rsum[k*2]=sum[k*2]=0; lsum[k*2+1]=rsum[k*2+1]=sum[k*2+1]=0; cover[k*2]=cover[k*2+1]=-1; } else { lsum[k*2]=rsum[k*2]=sum[k*2]=mid-l+1; lsum[k*2+1]=rsum[k*2+1]=sum[k*2+1]=r-mid; cover[k*2]=cover[k*2+1]=1; } cover[k]=0; } void build(int l,int r,int k){ if(l==r){ cover[k]=0; lsum[k]=rsum[k]=sum[k]=1; return; } int mid=l+r>>1; build(l,mid,k*2); build(mid+1,r,k*2+1); push_up(k,l,r); } int query(int l,int r,int k,int x){ if(l==r)return l; push_down(k,l,r); int mid=l+r>>1; if(sum[k*2]>=x)return query(l,mid,k*2,x); else if(rsum[k*2]+lsum[k*2+1]>=x) return mid-rsum[k*2]+1; else return query(mid+1,r,k*2+1,x); } void change(int l,int r,int k,int c,int x,int y){ if(l>=x&&r<=y){ cover[k]=c; lsum[k]=rsum[k]=sum[k]=c==-1?0:r-l+1; return; } push_down(k,l,r); int mid=l+r>>1; if(x<=mid) change(l,mid,k*2,c,x,y); if(y>mid) change(mid+1,r,k*2+1,c,x,y); push_up(k,l,r); } int main(){ scanf("%d%d",&n,&m); build(1,n,1); for(int i=1;i<=m;i++){ int opt,x,y;scanf("%d",&opt); if(opt==1){ scanf("%d",&x); if(sum[1]<x){ printf("0 "); continue; } int p=query(1,n,1,x); printf("%d ",p); change(1,n,1,-1,p,p+x-1); } else { scanf("%d%d",&x,&y); change(1,n,1,1,x,x+y-1); } } return 0; }