• 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
    ",ask(L,R));
        }
        
        return 0;
    }
    View Code
  • 相关阅读:
    .NET : 单元测试到底给我们带来什么
    .NET : 如何将16进制颜色代码转换为十进制
    LINQ : 谈谈LINQ TO SQL中的直接加载和延迟加载
    .NET : 单元测试的几个Attribute介绍
    .NET : 在单元测试中使用外部文件作为数据源
    再来谈谈json
    .NET : 关于图片格式的问题
    VSTS : 比较性能基准
    .NET : 如何将大文件写入到数据库中
    LINQ : 如何在JOIN或者GROUP BY的时候使用复合键
  • 原文地址:https://www.cnblogs.com/Robert-Yuan/p/5068234.html
Copyright © 2020-2023  润新知