1. 程式人生 > >hdu2871線段樹區間更新

hdu2871線段樹區間更新

線段樹區間更新 eject csdn pan pos ons 所有 發現 pro

不得已又挖了一個坑。。想來學習線段樹也有一段時間了,也有了些了解,但是在做題的

時候還是磕磕碰碰的,還是不夠熟練,還是要多做題(水題除外),多思考。

這是一道典型的線段樹區間更新,一定要使用延遲標記,同時又要使用區間合並。

區間合並的做法和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); }

hdu2871線段樹區間更新