不得已又挖了一个坑。。想来学习线段树也有一段时间了,也有了些了解,但是在做题的
时候还是磕磕碰碰的,还是不够熟练,还是要多做题(水题除外),多思考。
这是一道典型的线段树区间更新,一定要使用延迟标记,同时又要使用区间合并。
区间合并的做法和poj3667 Hotel这题是一样的。起先我想都使用线段树的查询,发现有困难
然后参考了http://blog.csdn.net/azheng51714/article/details/8089260这里的做法,即保存分配
过的区间的思路,因为所有的区间都是没有重合的,一个区间只能分配一次。但是无论我怎么
改都是TLE。。有哪位大神可以帮我看看。。
#include<cstdio> #include<algorithm> #include<map> #include<vector> using namespace std; const int maxn=50010; int llen[maxn*4],rlen[maxn*4],mlen[maxn*4]; int change[maxn*4]; struct seg{ int l,r; seg(){} seg(int _l,int _r):l(_l),r(_r){} bool operator<(const seg &s)const { return l<s.l; } }; vector<seg>sgmts; void pushUp(int root,int l,int r) { int len=r-l+1; llen[root]=llen[root*2]; rlen[root]=rlen[root*2+1]; if(llen[root*2]==len-len/2)llen[root]+=llen[root*2+1]; if(rlen[root*2+1]==len/2)rlen[root]+=rlen[root*2]; mlen[root]=max(rlen[root*2]+llen[root*2+1],max(mlen[root*2],mlen[root*2+1])); } void pushDown(int root,int l,int r) { if(change[root]!=-1){ change[root*2]=change[root*2+1]=change[root]; int t=change[root],len=r-l+1; llen[root*2]=rlen[root*2]=mlen[root*2]=t?0:len-len/2;//0表示释放,1表示分配 llen[root*2+1]=rlen[root*2+1]=mlen[root*2+1]=t?0:len/2; change[root]=-1; } } void build(int root,int l,int r) { change[root]=-1; llen[root]=rlen[root]=mlen[root]=r-l+1; if(l==r)return; int mid=(l+r)/2; build(root*2,l,mid); build(root*2+1,mid+1,r); } void update(int root,int v,int L,int R,int l,int r) { if(R<l||L>r)return; if(L<=l&&r<=R){ int len=r-l+1; change[root]=v; llen[root]=rlen[root]=mlen[root]=v?0:len;//0表示释放,1表示分配/// return; } pushDown(root,l,r); int mid=(l+r)/2; if(mid>=L)update(root*2,v,L,R,l,mid); if(mid<R)update(root*2+1,v,L,R,mid+1,r); pushUp(root,l,r); } int query2(int root,int w,int l,int r) { if(l==r)return l;/// pushDown(root,l,r); int mid=(l+r)/2; if(mlen[root*2]>=w)return query2(root*2,w,l,mid); else if(rlen[root*2]+llen[root*2+1]>=w)return mid-rlen[root*2]+1; else return query2(root*2+1,w,mid+1,r); } int main() { //freopen("in.txt","r",stdin); int N,M; while(scanf("%d%d\n",&N,&M)!=EOF){ char cmd[10]; int n; build(1,1,N); sgmts.clear(); while(M--){ scanf("%s",cmd); if(cmd[0]==‘N‘){ scanf("%d",&n); if(mlen[1]<n)printf("Reject New\n"); else { int p=query2(1,n,1,N); update(1,1,p,p+n-1,1,N); //sgmts.push_back(seg(p,p+n-1)); //sort(sgmts.begin(),sgmts.end()); seg t=seg(p,p+n-1); auto itr=upper_bound(sgmts.begin(),sgmts.end(),t); sgmts.insert(itr,t); printf("New at %d\n",p); } } if(cmd[0]==‘F‘){ scanf("%d",&n); seg t=seg(n,n); auto p=upper_bound(sgmts.begin(),sgmts.end(),t); if(p==sgmts.begin()||(--p)->r<n)printf("Reject Free\n"); else { update(1,0,p->l,p->r,1,N); printf("Free from %d to %d\n",p->l,p->r); sgmts.erase(p); } } if(cmd[0]==‘G‘){ scanf("%d",&n); if(n>sgmts.size())printf("Reject Get\n"); else{ printf("Get at %d\n",sgmts[n-1].l); } } if(cmd[0]==‘R‘){ //build(1,1,N);// update(1,0,1,N,1,N); sgmts.clear(); printf("Reset Now\n"); } } printf("\n"); } //while(1); }