hdu2871线段树区间更新

Posted MalcolmMeng

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了hdu2871线段树区间更新相关的知识,希望对你有一定的参考价值。

不得已又挖了一个坑。。想来学习线段树也有一段时间了,也有了些了解,但是在做题的

时候还是磕磕碰碰的,还是不够熟练,还是要多做题(水题除外),多思考。

这是一道典型的线段树区间更新,一定要使用延迟标记,同时又要使用区间合并。

区间合并的做法和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线段树区间更新的主要内容,如果未能解决你的问题,请参考以下文章

HDU 3577 Fast Arrangement (线段树区间更新)

HDU1166敌兵布阵(线段树单点更新)

HDU 1698 Just a Hook 线段树区间更新

hdu 3308 线段树 区间合并+单点更新+区间查询

hdu 1698(线段树区间更新)

hdu 1698 线段树 区间更新