BZOJ 1251 序列终结者

AC通道:http://www.lydsy.com/JudgeOnline/problem.php?id=1251

 

这题就是充分利用文艺平衡树那题留下的心理阴影啊...

总之,我们已经知道平衡树可以像线段树一样操作[非递归线段树的感觉...],不过平衡树支持神奇的翻转操作...[这个见文艺平衡树]

 

然后就是tag的下传和向上更新了...一定要注意细节啊~什么左子树右子树是不是为空,还是要仔细看一看的啦...

 

#include<cstdio>
#include<cstring>
#include<algorithm>

using namespace std;

inline int in(){
    int x=0,f=1;char ch=getchar();
    while((ch>'9' || ch<'0') && ch!='-') ch=getchar();
    if(ch=='-') f=-1,ch=getchar();
    while(ch>='0' && ch<='9') x=x*10+ch-'0',ch=getchar();
    return x*f;
}

const int maxn=100010;

struct Node{
    int Mx,sz,dt;
    int l,r,f;
    int ad;
    bool mk;
    
    void trans(){swap(l,r);}
}s[maxn];

int rt,n,m;

void update(int x){
    s[x].sz=s[s[x].l].sz+s[s[x].r].sz+1;
    
    s[x].Mx=s[x].dt;
    if(s[x].l) s[x].Mx=max(s[x].Mx,s[s[x].l].Mx);
    if(s[x].r) s[x].Mx=max(s[x].Mx,s[s[x].r].Mx);
}

void push_down(int x){
    if(s[x].mk){
        s[x].trans();s[x].mk=0;
        if(s[x].l) s[s[x].l].mk^=1;
        if(s[x].r) s[s[x].r].mk^=1;
    }
    if(s[x].ad){
        if(s[x].l) {s[s[x].l].ad+=s[x].ad;s[s[x].l].dt+=s[x].ad;s[s[x].l].Mx+=s[x].ad;}
        if(s[x].r) {s[s[x].r].ad+=s[x].ad;s[s[x].r].dt+=s[x].ad;s[s[x].r].Mx+=s[x].ad;}
        s[x].ad=0;
    }
}

int build(int l,int r){
    if(l>r) return 0;
    int mid=(l+r)>>1;
    s[mid].l=build(l,mid-1);
    s[mid].r=build(mid+1,r);
    update(mid);
    if(s[mid].l) s[s[mid].l].f=mid;
    if(s[mid].r) s[s[mid].r].f=mid;
    return mid;
}

void zig(int x){
    int y=s[x].f;
    
    s[x].f=s[y].f;
    if(s[y].f){
        if(y==s[s[y].f].l) s[s[y].f].l=x;
        else s[s[y].f].r=x;
    }
    
    s[y].l=s[x].r;
    if(s[x].r) s[s[x].r].f=y;
    
    s[x].r=y;s[y].f=x;
    
    update(y),update(x);
}

void zag(int x){
    int y=s[x].f;
    
    s[x].f=s[y].f;
    if(s[y].f){
        if(y==s[s[y].f].l) s[s[y].f].l=x;
        else s[s[y].f].r=x;
    }
    
    s[y].r=s[x].l;
    if(s[x].l) s[s[x].l].f=y;
    
    s[x].l=y;s[y].f=x;
    
    update(y),update(x);
}

void Splay(int x,int gf){
    int y;
    while(s[x].f!=gf){
        y=s[x].f;
        if(s[y].f==gf){
            if(x==s[y].l) zig(x);
            else zag(x);
        }
        else{
            int z=s[y].f;
            if(y==s[z].l){
                if(x==s[y].l) zig(y),zig(x);
                else zag(x),zig(x);
            }
            else{
                if(x==s[y].r) zag(y),zag(x);
                else zig(x),zag(x);
            }
        }
    }
    
    if(!gf) rt=x;
}

int Find(int k){
    int p=rt;
    while(p){
        push_down(p);
        if(k<=s[s[p].l].sz) p=s[p].l;
        else{
            k-=s[s[p].l].sz;
            if(k==1) return p;
            k--;p=s[p].r;
        }
    }
}

void add(int L,int R,int k){
    int a=Find(L),b=Find(R+2);
    Splay(a,0);Splay(b,a);
    s[s[b].l].ad+=k,s[s[b].l].dt+=k,s[s[b].l].Mx+=k;
}

void rev(int L,int R){
    int a=Find(L),b=Find(R+2);
    Splay(a,0);Splay(b,a);
    s[s[b].l].mk^=1;
}

int ask(int L,int R){
    int a=Find(L),b=Find(R+2);
    Splay(a,0);Splay(b,a);
    return s[s[b].l].Mx;
}

int main(){
#ifndef ONLINE_JUDGE
    freopen("1512.in","r",stdin);
    freopen("1512.out","w",stdout);
#endif
    
    int ord,L,R,k;
    
    n=in(),m=in();
    rt=build(1,n+2);
    
    while(m--){
        ord=in();L=in(),R=in();
        if(ord==1)
            k=in(),add(L,R,k);
        else if(ord==2)
            rev(L,R);
        else
            printf("%d\n",ask(L,R));
    }
    
    return 0;
}
View Code

 

posted @ 2015-12-22 21:42  诚叙  阅读(265)  评论(0编辑  收藏  举报