不得不说这个题确实是练习线段树的好题,跟Hotel比较类似,但总体来说要难不少。最开始一直想的记录的问题,后来看到别人用vector才发现这样用使代码好写好多~
多的不说了,看代码吧。其实更新那些都还比较常规,主要是vector的运用。
代码:
#include<cstdio> #include<cstring> #include<iostream> #include<vector> #include<algorithm> using namespace std; const int maxn=6e4; const int maxm=maxn*3; struct Node { int l; int r; int len; int res; int resl; int resr; bool isupdate; }t[maxm]; struct Operation { int begin; int end; Operation(){} Operation(int sbegin,int send) { begin=sbegin; end=send; } bool operator < (const Operation &a)const { return begin<a.begin; } }; int n,m; vector<Operation> oper; vector<Operation>::iterator it; void Build(int l,int r,int index) { t[index].l=l; t[index].r=r; t[index].len=r-l+1; t[index].isupdate=false; t[index].resl=t[index].resr=t[index].res=t[index].len; if(l==r) return; int mid=(l+r)>>1; Build(l,mid,index<<1); Build(mid+1,r,index<<1|1); } void PushUp(int index) { if(t[index<<1].resl==t[index<<1].len) t[index].resl=t[index<<1].len+t[index<<1|1].resl; else t[index].resl=t[index<<1].resl; if(t[index<<1|1].resr==t[index<<1|1].len) t[index].resr=t[index<<1|1].len+t[index<<1].resr; else t[index].resr=t[index<<1|1].resr; t[index].res=max(t[index<<1].res,t[index<<1|1].res); t[index].res=max(t[index].res,max(t[index].resl,t[index].resr)); t[index].res=max(t[index].res,t[index<<1].resr+t[index<<1|1].resl); } void PushDown(int index) { t[index].isupdate=false; if(t[index].l==t[index].r) return; t[index<<1].isupdate=t[index<<1|1].isupdate=true; if(t[index].res==t[index].len) { t[index<<1].resl=t[index<<1].resr=t[index<<1].res=t[index<<1].len; t[index<<1|1].resl=t[index<<1|1].resr=t[index<<1|1].res=t[index<<1|1].len; } if(!t[index].res) { t[index<<1].resl=t[index<<1].resr=t[index<<1].res=0; t[index<<1|1].resl=t[index<<1|1].resr=t[index<<1|1].res=0; } } void Update(int l,int r,int index,int val) { if(t[index].isupdate) PushDown(index); if(t[index].l==l&&t[index].r==r) { t[index].isupdate=true; if(!val) t[index].res=t[index].resl=t[index].resr=t[index].len; else t[index].res=t[index].resl=t[index].resr=0; return; } int mid=(t[index].l+t[index].r)>>1; if(r<=mid) Update(l,r,index<<1,val); else if(l>mid) Update(l,r,index<<1|1,val); else { Update(l,mid,index<<1,val); Update(mid+1,r,index<<1|1,val); } PushUp(index); } int Query(int index,int val) { if(t[index].res<val) return -1; if(t[index].isupdate) PushDown(index); if(t[index].l==t[index].r) return t[index].l; if(t[index<<1].res>=val) return Query(index<<1,val); if(t[index<<1].resr&&t[index<<1].resr+t[index<<1|1].resl>=val) return t[index<<1].r-t[index<<1].resr+1; return Query(index<<1|1,val); } int main() { while(scanf("%d%d",&n,&m)!=EOF) { Build(1,n,1); oper.clear(); while(m--) { char op[20]; scanf("%s",op); if(op[0]=='N') { //New int val; scanf("%d",&val); int ans=Query(1,val); if(ans==-1) { printf("Reject New\n"); continue; } else printf("New at %d\n",ans); Update(ans,ans+val-1,1,1); Operation opt=Operation(ans,ans+val-1); it=upper_bound(oper.begin(),oper.end(),opt); oper.insert(it,opt); } else if(op[0]=='F') { int val; scanf("%d",&val); Operation opt=Operation(val,val); it=upper_bound(oper.begin(),oper.end(),opt); int index=it-oper.begin()-1; if(index==-1||oper[index].end<val) { printf("Reject Free\n"); continue; } printf("Free from %d to %d\n",oper[index].begin,oper[index].end); Update(oper[index].begin,oper[index].end,1,0); oper.erase(oper.begin()+index); } else if(op[0]=='G') { int val; scanf("%d",&val); if(val>oper.size()) printf("Reject Get\n"); else printf("Get at %d\n",oper[val-1].begin); } else { //Reset oper.clear(); Update(1,n,1,0); printf("Reset Now\n"); } } printf("\n"); } return 0; }