洛谷 P2894 [USACO08FEB]酒店
用线段树维护三个值:区间最长空位长度,从左端点可以延伸的最长空位长度,从右端点可以延伸的最长空位长度。
#include<complex> #include<cstdio> using namespace std; const int N=2e6+7; int n,m; int len[N],Max[N],maxl[N],maxr[N],lazy[N]; int qread() { int x=0; char ch=getchar(); while(ch<'0' || ch>'9')ch=getchar(); while(ch>='0' && ch<='9'){x=x*10+ch-'0';ch=getchar();} return x; } void PushUp(int rt) { if(Max[rt<<1]==len[rt<<1])maxl[rt]=Max[rt<<1]+maxl[rt<<1|1]; else maxl[rt]=maxl[rt<<1]; if(Max[rt<<1|1]==len[rt<<1|1])maxr[rt]=Max[rt<<1|1]+maxr[rt<<1]; else maxr[rt]=maxr[rt<<1|1]; Max[rt]=max(max(Max[rt<<1],Max[rt<<1|1]),maxr[rt<<1]+maxl[rt<<1|1]); } void PushDown(int rt) { if(!lazy[rt])return; lazy[rt<<1]=lazy[rt<<1|1]=lazy[rt]; if(lazy[rt]==1) { Max[rt<<1]=maxl[rt<<1]=maxr[rt<<1]=0; Max[rt<<1|1]=maxl[rt<<1|1]=maxr[rt<<1|1]=0; } else { Max[rt<<1]=maxl[rt<<1]=maxr[rt<<1]=len[rt<<1]; Max[rt<<1|1]=maxl[rt<<1|1]=maxr[rt<<1|1]=len[rt<<1|1]; } lazy[rt]=0; } void Build(int l,int r,int rt) { maxl[rt]=maxr[rt]=Max[rt]=len[rt]=r-l+1; if(l==r)return; int mid=l+r>>1; Build(l,mid,rt<<1);Build(mid+1,r,rt<<1|1); } void Modify(int l,int r,int rt,int nowl,int nowr,int v) { if(nowl<=l && r<=nowr) { if(v==1)Max[rt]=maxl[rt]=maxr[rt]=0; else Max[rt]=maxl[rt]=maxr[rt]=len[rt]; lazy[rt]=v; return; } PushDown(rt); int mid=l+r>>1; if(nowl<=mid)Modify(l,mid,rt<<1,nowl,nowr,v); if(mid<nowr)Modify(mid+1,r,rt<<1|1,nowl,nowr,v); PushUp(rt); } int Query(int l,int r,int rt,int p) { if(l==r)return l; PushDown(rt); int mid=l+r>>1; if(Max[rt<<1]>=p)return Query(l,mid,rt<<1,p); if(maxr[rt<<1]+maxl[rt<<1|1]>=p)return mid-maxr[rt<<1]+1; return Query(mid+1,r,rt<<1|1,p); } int main() { scanf("%d%d",&n,&m); Build(1,n,1); int p,l,r,x; while(m--) { p=qread(); if(p==1) { x=qread(); if(Max[1]<x){puts("0");continue;} int tot=Query(1,n,1,x); printf("%d\n",tot); Modify(1,n,1,tot,tot+x-1,1); } else { l=qread();r=qread(); Modify(1,n,1,l,l+r-1,2); } } return 0; }