• 并不对劲的文艺平衡树


    这道题在好多测评网站都可以提交。

    这次用平衡树维护的不是每个数的值,而是顺序。

    至于区间操作,每次把左边界左边的那个点旋转到根,把右边界右边的那个点旋转到根的右儿子。

    然后你就会惊讶(并不)地发现:这个区间都被转到蓝色区域去了!(毕竟是l-1<rank<r+1的部分)

    这样就可以在这个区间的根节点,也就是图中的点x,上进行标记。

    至于pushdown的细节,也没什么好说的。

    但要注意l-1和r+1可能会是不存在的点,因此在建splay时要在左右边界额外各放一个。

    (并不对劲的一点看法:这题应该能用别的平衡树做,就是每次把该转到根的转到根再转回去吧,听说常数会更小。但有什么用呢?反正心中有党常数极小)

    这道题为什么要用splay维护区间反转呢?想必是和某个L开头T结尾的玩意儿有关的。

    #include<algorithm>
    #include<iostream>
    #include<cstring>
    #include<cstdio>
    #include<cmath>
    #include<iomanip>
    #include<cstdlib>
    #define maxn 100010
    #define mod 1000000
    using namespace std;
    int read(){
        int x=0,f=1;
        char ch=getchar();
        while(isdigit(ch)==0 && ch!='-')ch=getchar();
        if(ch=='-')f=-1;
        while(isdigit(ch))x=x*10+ch-'0',ch=getchar();
        return x*f;
    }
    typedef struct node{
        int son[2],fa;//0左,1右 
        int key,re,siz;
    }Tree;
    typedef struct array{
        int a[maxn];
    }A;
    int n,m;
    A b;
    struct Splay
    {
        int cnt,root;
        Tree x[maxn];
        inline void pushdown(int u){
            if(x[u].re){
                x[u].re=0;
                swap(x[u].son[0],x[u].son[1]);
                x[x[u].son[0]].re^=1;
                x[x[u].son[1]].re^=1;
            }
        }
        inline void pushup(int u){
            x[u].siz=x[x[u].son[0]].siz+x[x[u].son[1]].siz+1;    
        }
        inline void rot(int u){
            int fu=x[u].fa,ffu=x[fu].fa,l=(x[fu].son[1]==u),r=l^1;
            int l2=(fu==x[ffu].son[1]);
            x[ffu].son[l2]=u;
            x[u].fa=ffu;
            x[fu].fa=u;
            x[fu].son[l]=x[u].son[r];
            x[x[u].son[r]].fa=fu;
            x[u].son[r]=fu;
            pushup(fu),pushup(u);
        }
        inline void splay(int u,int k){
            while(x[u].fa!=k){
                int fu=x[u].fa,ffu=x[fu].fa;
                if(ffu!=k){
                    if((x[ffu].son[0]==x[u].fa)^(x[fu].son[0]==u))
                        rot(u);
                    else rot(fu);
                }
                rot(u);
            }
            if(k==0)root=u;
        }
        inline int res(int k,int f){
            x[++cnt].key=k,
            x[cnt].fa=f,
            x[cnt].re=0;x[cnt].siz=1;
            return cnt;
        }
        /*inline void ins(int k){
            int lst=0,u=root;
            while(u){
                pushdown(u);
                if(x[x[u].son[0]].siz+1==k)break;
                x[u].siz++;int rk=x[x[u].son[0]].siz+1;
                lst=u,u=x[u].son[rk<k],k=k>rk?k-rk:k;
            }
            if(u==0){
                u=res(k,lst,0,0);
                if(lst)x[lst].son[x[lst].key<k]=u;
            }
            splay(u,0);
        }*/
        inline int rnk(int k){//the number of the kth number
            int u=root;
            if(u==0)return 0;
            while(u){
                pushdown(u);
                int rk=x[x[u].son[0]].siz+1;
                if(rk==k)break;
                u=x[u].son[k>rk];
                k=k>rk?k-rk:k;
            }
            //splay(u,0);
            return u;
        }
        /*inline void del(int k){
            int lk=rnk(k-1),
            rk=rnk(k+1);
            splay(lk,0),splay(rk,lk);
            x[rk].son[0]=0;
        }*/
        inline void rev(int l,int r){
            int lk=rnk(l-1),rk=rnk(r+1);
            splay(lk,0),splay(rk,lk);
            x[x[rk].son[0]].re^=1;
            pushdown(x[rk].son[0]);
        }
        inline void prt(int u){
            pushdown(u);
            if(x[u].son[0])prt(x[u].son[0]);
            if(x[u].key!=-1)printf("%d ",x[u].key);
            if(x[u].son[1])prt(x[u].son[1]);
        }
        void start(){
            cnt=root=0;
        }
    }t;
    inline int bld(int l,int r,int lst){
        if(l>r)return 0;
        if(l==r){
            return t.res(b.a[l],lst);
        }
        else{
            int m=(l+r)>>1;
            int u=t.res(b.a[m],lst);
            int ls=bld(l,m-1,u);
            int rs=bld(m+1,r,u);
            t.x[u].son[0]=ls,t.x[u].son[1]=rs;
            t.pushup(u);
            return u;
        }    
    }
    int main()
    {
    //cout<<" I hate Splay"<<endl;
        n=read(),m=read();
        b.a[0]=b.a[n+1]=-1;
        for(int i=1;i<=n;i++)
            b.a[i]=i;
           t.root=1;
        bld(0,n+1,0);
        while(m--){
            int x=read(),y=read();
            t.rev(x+1,y+1);
        }
        t.prt(t.root);
        return 0;
    }
    并不对劲的文艺平衡树

    其实这是AC的

  • 相关阅读:
    [转载] boost安装笔记——vs2008
    CSS 中的分离、抽象和层叠(转载)
    web server大全之GoAhead移植(转载)
    MIT牛人解说数学体系(转载)
    CodeBlocks 编辑器设置绿色背景
    Eclipse+Tomcat+Mysql构建J2EE开发环境(转载)
    堆和栈的区别——给初学者 (装载)
    Eclipse下设置github开发环境
    [原创] MyEclipse配置Tomcat和MySQL
    VS2008下编译Boost(转载+更改)
  • 原文地址:https://www.cnblogs.com/xzyf/p/8194933.html
Copyright © 2020-2023  润新知