• Splay学习


    splay详解

    基本操作:

    void rotate(int x){
        int y=tr[x].fa,z=tr[y].fa,c=(tr[y].son[0]==x);
        tr[y].son[c^1]=tr[x].son[c];
        tr[tr[x].son[c]].fa=y;
        tr[x].son[c]=y;tr[y].fa=x;tr[x].fa=z;
        if(z)tr[z].son[tr[z].son[1]==y]=x;
        pushup(y);pushup(x);
        return ;
    }
    void splay(int x,int goal){
        while(tr[x].fa!=goal){
            int y=tr[x].fa,z=tr[y].fa;
            if(z!=goal)(tr[z].son[0]==y)^(tr[y].son[0]==x)?rotate(x):rotate(y);
            rotate(x);
        }
        if(!goal)root=x;
    
    }

    一些小细节:

    • splay双旋
    • 经常设置虚点,使得完成某些包含开头或结尾的操作
    • splay tree是一种二叉搜索树,它的左儿子的权值<自己的权值<右儿子的权值,节点的权值不仅可以代表数值,也可以代表序列的顺序

    插入、删除、查数x排名、查排名为x的数,前驱后继

    //luogu【模板】普通平衡树
    #include<functional>
    #include<algorithm>
    #include<iostream>
    #include<cstdlib>
    #include<cstring>
    #include<cstdio>
    #include<cmath>
    #include<queue>
    #define ll long long
    using namespace std;
    const int maxn=2000000+101;
    int read(){
        int x=0,f=1;char ch=getchar();
        for(;!isdigit(ch);ch=getchar())if(ch=='-')f=-1;
        for(;isdigit(ch);ch=getchar())x=x*10+ch-'0';
        return x*f;
    }
    
    int n,root,tot;
    struct wzq{int son[2],v,fa,cnt,sz;}tr[maxn];
    
    void pushup(int x){tr[x].sz=tr[tr[x].son[0]].sz+tr[tr[x].son[1]].sz+tr[x].cnt;}
    void rotate(int x){
        int y=tr[x].fa,z=tr[y].fa,c=(tr[y].son[0]==x);
        tr[y].son[c^1]=tr[x].son[c];
        tr[tr[x].son[c]].fa=y;tr[x].son[c]=y;
        tr[y].fa=x;tr[x].fa=z;
        if(z)tr[z].son[tr[z].son[1]==y]=x;
        pushup(y);pushup(x);
        return ;
    }
    void splay(int x,int goal){
        while(tr[x].fa!=goal){
            int y=tr[x].fa,z=tr[y].fa;
            if(z!=goal)(tr[z].son[0]==y)^(tr[y].son[0]==x)?rotate(x):rotate(y);
            rotate(x);
        }
        if(!goal)root=x;
    
    }
    void insert(int val){
        int x=root,f=0;
        while(x && tr[x].v!=val){f=x;x=tr[x].son[tr[x].v<val];}
        if(x){tr[x].cnt++;splay(x,0);return ;}
        x=++tot;
        if(f)tr[f].son[tr[f].v<val]=x;
        tr[x].son[0]=tr[x].son[1]=0;
        tr[x].v=val;tr[x].fa=f;tr[x].cnt=tr[x].sz=1;
        splay(x,0);return ;
    }
    void Find(int val){
        int x=root;
        if(!x)return ;
        while(1){
            if(tr[x].v==val){splay(x,0);return ;}
            if(tr[x].son[tr[x].v<val])x=tr[x].son[tr[x].v<val];
            else {splay(x,0);return ;}
        }
    }
    int Next(int val,int f){  //0前 1后
        Find(val);int x=root;
        if((tr[x].v<val && !f) || (tr[x].v>val && f))return x;
        x=tr[x].son[f];
        while(tr[x].son[f^1])x=tr[x].son[f^1];
        return x;
    }
    void delet(int val){
        int qian=Next(val,0),hou=Next(val,1);
        splay(qian,0);splay(hou,qian);
        int x=tr[hou].son[0];
        if(tr[x].cnt>1){
            tr[x].cnt--;
            splay(x,0);
        }
        else tr[hou].son[0]=0;
        return ;
    }
    int Kth(int k){
        int x=root;
        while(1){
            int t=tr[x].son[0];
            if(tr[t].sz+tr[x].cnt<k){
                k=k-tr[t].sz-tr[x].cnt;
                x=tr[x].son[1];
            }
            else {
                if(tr[t].sz<k)return tr[x].v;
                x=t;
            }
        }
    }
    int main(){
        insert(2147483647);insert(-2147483647);
        n=read();int num=0;
        for(int i=1;i<=n;i++){
            int opt=read(),x=read();
            if(opt==1)insert(x);
            if(opt==2)delet(x);
            if(opt==3){Find(x);printf("%d
    ",tr[tr[root].son[0]].sz);}
            if(opt==4){printf("%d
    ",Kth(x+1));}
            if(opt==5){printf("%d
    ",tr[Next(x,0)].v);}
            if(opt==6){printf("%d
    ",tr[Next(x,1)].v);}
        }
        return 0;
    }

    区间删除、插入、翻转

    //HDU3487
    #include<functional>
    #include<algorithm>
    #include<iostream>
    #include<cstdlib>
    #include<cstring>
    #include<string>
    #include<cstdio>
    #include<cmath>
    #include<queue>
    #define ll long long 
    using namespace std;
    const int maxn=500000+101;
    const int MOD=998244353;
    const int inf=2147483647;
    int read(){
        int x=0,f=1;char ch=getchar();
        for(;!isdigit(ch);ch=getchar())if(ch=='-')f=-1;
        for(;isdigit(ch);ch=getchar())x=x*10+ch-'0';
        return x*f;
    }
    int n,m,tot,root,sum;
    struct wzq{int v,son[2],cnt,sz,fa,rev;}tr[maxn];
    void update(int x){tr[x].sz=tr[x].cnt+tr[tr[x].son[0]].sz+tr[tr[x].son[1]].sz;}
    void pushdown(int x){
        if(tr[x].rev){
            tr[x].rev^=1;
            swap(tr[x].son[1],tr[x].son[0]);
            tr[tr[x].son[1]].rev^=1;
            tr[tr[x].son[0]].rev^=1;
        }
        return ;
    }
    void rotate(int x){
        pushdown(x);
        int y=tr[x].fa,z=tr[y].fa,c=(tr[y].son[0]==x);
        tr[y].son[c^1]=tr[x].son[c];
        tr[y].fa=x;tr[tr[x].son[c]].fa=y;tr[x].fa=z;
        tr[x].son[c]=y;
        if(z)tr[z].son[tr[z].son[1]==y]=x;
        update(y);update(x);
    }
    void splay(int x,int goal){
        while(tr[x].fa!=goal){
            int y=tr[x].fa,z=tr[y].fa;
            if(z!=goal)(tr[y].son[0]==x)^(tr[z].son[0]==y)?rotate(x):rotate(y);
            rotate(x);
        }
        if(!goal)root=x;
    }
    int Kth(int val){
        int x=root;
        while(1){
            pushdown(x);
            int left=tr[x].son[0],right=tr[x].son[1];
            if(val>tr[left].sz+tr[x].cnt)val-=tr[left].sz+tr[x].cnt,x=tr[x].son[1];
            else {
                if(val<=tr[left].sz)x=left;
                else return x;
            }
        }
    }
    int New(int f,int val){
        int x=++tot;tr[x].v=val;
        tr[x].fa=f;tr[x].cnt=tr[x].sz=1;
        tr[x].son[0]=tr[x].son[1]=tr[x].rev=0;
        return x;
    }
    void build(int f,int l,int r,int &t){
        if(l>r)return;
        int mid=(l+r)>>1;t=New(f,mid);
        build(t,l,mid-1,tr[t].son[0]);
        build(t,mid+1,r,tr[t].son[1]);
        update(t);return ;
    }
    void init(){
        sum=tot=root=0;tr[0].son[0]=tr[0].son[1]=tr[0].sz=0;
        root=New(0,-inf);tr[root].son[1]=New(root,inf);
        tr[root].sz=2;
        build(tr[root].son[1],1,n,tr[tr[root].son[1]].son[0]);
        update(tr[root].son[1]);update(root);
    }
    void prin(int x){
        pushdown(x);
        if(!x)return ;
        prin(tr[x].son[0]);
        if(tr[x].v!=inf && tr[x].v!=-inf){
            sum++;
            if(sum!=n)printf("%d ",tr[x].v);
            else printf("%d
    ",tr[x].v);
        }
        prin(tr[x].son[1]);
    }
    int main(){
        while(1){
            n=read();m=read();if(n<0 && m<0)break;
            init();
            for(int i=1;i<=m;i++){
                char ch[10];cin>>ch;int x,y,z;
                if(ch[0]=='C'){
                    x=read()+1;y=read()+1;z=read()+1;
                    int xx=Kth(x-1),yy=Kth(y+1);
                    splay(xx,0);splay(yy,xx);
                    int las=tr[yy].son[0];
                    tr[yy].son[0]=0;update(yy);update(xx);
                    xx=Kth(z),yy=Kth(z+1);
                    splay(xx,0);splay(yy,xx);
                    tr[yy].son[0]=las;tr[las].fa=yy;
                    update(yy);update(xx);
                }
                else {
                    x=read()+1;y=read()+1;
                    splay(Kth(x-1),0);splay(Kth(y+1),Kth(x-1));
                    tr[tr[tr[root].son[1]].son[0]].rev^=1;
                }
            }
            prin(root);
        }
        return 0;
    }

     splay区间操作大全

    插入、删除、区间查询、区间翻转、区间旋转、区间修改

    //poj3580
    #include<functional>
    #include<algorithm>
    #include<iostream>
    #include<cstdlib>
    #include<cstring>
    #include<string>
    #include<cstdio>
    #include<cmath>
    #include<queue>
    #define ll long long 
    using namespace std;
    const int maxn=100000+101;
    const int MOD=998244353;
    const int inf=2147483647;
    int read(){
        int x=0,f=1;char ch=getchar();
        for(;!isdigit(ch);ch=getchar())if(ch=='-')f=-1;
        for(;isdigit(ch);ch=getchar())x=x*10+ch-'0';
        return x*f;
    }
    int n,m,a[maxn];
    int root,tot;
    struct wzq{int v,son[2],sz,fa,cnt,lz,minv,rev;}tr[maxn];
    void update(int x){
        tr[x].minv=tr[x].v;
        tr[x].sz=tr[x].cnt+tr[tr[x].son[0]].sz+tr[tr[x].son[1]].sz;
        if(tr[x].son[0])tr[x].minv=min(tr[x].minv,tr[tr[x].son[0]].minv);
        if(tr[x].son[1])tr[x].minv=min(tr[x].minv,tr[tr[x].son[1]].minv);
    }
    void pushdown(int x){
        if(tr[x].rev){
            tr[x].rev=0;
            swap(tr[x].son[0],tr[x].son[1]);
            tr[tr[x].son[0]].rev^=1;
            tr[tr[x].son[1]].rev^=1;
        }
        if(tr[x].lz){
            tr[tr[x].son[0]].lz+=tr[x].lz;tr[tr[x].son[1]].lz+=tr[x].lz;
            tr[tr[x].son[0]].minv+=tr[x].lz;tr[tr[x].son[1]].minv+=tr[x].lz;
            tr[tr[x].son[0]].v+=tr[x].lz;tr[tr[x].son[1]].v+=tr[x].lz;
            tr[x].lz=0;
        }
        return ;
    }
    void rotate(int x){
        pushdown(x);
        int y=tr[x].fa,z=tr[y].fa,c=(tr[y].son[0]==x);
        tr[y].son[c^1]=tr[x].son[c];
        tr[y].fa=x;tr[tr[x].son[c]].fa=y;tr[x].fa=z;
        tr[x].son[c]=y;
        if(z)tr[z].son[tr[z].son[1]==y]=x;
        update(y);update(x);
    }
    
    void splay(int x,int goal){
        while(tr[x].fa!=goal){
            int y=tr[x].fa,z=tr[y].fa;
            if(z!=goal)(tr[y].son[0]==x)^(tr[z].son[0]==y)?rotate(x):rotate(y);
            rotate(x);
        }
        if(!goal)root=x;
    }
    int New(int f,int val){
        int x=++tot;
        tr[x].fa=f;tr[x].sz=tr[x].cnt=1;tr[x].v=tr[x].minv=val;
        tr[x].lz=tr[x].rev=tr[x].son[0]=tr[x].son[1]=0;
        return x;
    }
    void build(int f,int l,int r,int &t){
        if(l>r)return ;
        int mid=(l+r)>>1;
        t=New(f,a[mid]);
        build(t,l,mid-1,tr[t].son[0]);
        build(t,mid+1,r,tr[t].son[1]);
        update(t);
    }
    void init(){
        root=New(0,-inf);tr[root].son[1]=New(root,inf);
        build(tr[root].son[1],1,n,tr[tr[root].son[1]].son[0]);
        update(tr[root].son[1]);update(root);
    }
    int Kth(int val){
        int x=root;
        while(1){
            pushdown(x);
            int left=tr[x].son[0],right=tr[x].son[1];
            if(val>tr[left].sz+tr[x].cnt)val-=tr[left].sz+tr[x].cnt,x=tr[x].son[1];
            else {
                if(val<=tr[left].sz)x=left;
                else return x;
            }
        }
    }
    int main(){
        n=read();for(int i=1;i<=n;i++)a[i]=read();
        m=read();init();
        for(int i=1;i<=m;i++){
            char ch[10];cin>>ch;int x,y,d;
            if(ch[0]=='A'){
                x=read()+1;y=read()+1;d=read();
                int xx=Kth(x-1),yy=Kth(y+1);
                splay(xx,0);splay(yy,xx);
                tr[tr[yy].son[0]].lz+=d;
                tr[tr[yy].son[0]].minv+=d;
                tr[tr[yy].son[0]].v+=d;
                update(yy);update(xx);
            }
            else if(ch[0]=='R' && ch[3]=='E'){
                x=read()+1,y=read()+1;
                int xx=Kth(x-1),yy=Kth(y+1);
                splay(xx,0);splay(yy,xx);
                tr[tr[yy].son[0]].rev^=1;
            }
            else if(ch[0]=='R' && ch[3]=='O'){
                x=read()+1,y=read()+1,d=read();d=d%(y-x+1);
                if(d==0)continue;
                int x1=Kth(y-d),y1=Kth(y+1);
                splay(x1,0);splay(y1,x1);
                int tmp=tr[y1].son[0];tr[y1].son[0]=0;update(y1);update(x1);
                int xx=Kth(x-1),yy=Kth(x);
                splay(xx,0);splay(yy,xx);
                tr[yy].son[0]=tmp;tr[tmp].fa=yy;update(yy);update(xx);
            }
            else if(ch[0]=='D'){
                x=read()+1;int xx=Kth(x-1),yy=Kth(x+1);
                splay(xx,0);splay(yy,xx);
                tr[yy].son[0]=0;update(yy);update(xx);
            }
            else if(ch[0]=='M'){
                x=read()+1,y=read()+1;
                int xx=Kth(x-1),yy=Kth(y+1);
                splay(xx,0);splay(yy,xx);
                printf("%d
    ",tr[tr[yy].son[0]].minv);
            }
            else if(ch[0]=='I'){
                x=read()+1;y=read();
                int xx=Kth(x),yy=Kth(x+1);
                splay(xx,0);splay(yy,xx);
                int kk=New(yy,y);
                tr[yy].son[0]=kk;update(yy);update(xx);
            }
        }
        return 0;
    }
  • 相关阅读:
    阿里云通过465端口发送邮件绕过25端口
    阿里云子账号Policy授权规则明细
    蓝鲸cmdb平台架构
    库文件缺失问题修复
    centos7.2中启动polkit服务启动失败
    Linux升级GCC
    Ubuntu18.04服务器使用netplan网络构建桥接kvm虚拟机
    常用服务部署脚本(nodejs,pyenv,go,redis,)
    anaconda安装教程(之前安装过python)
    【PHP】array_unique与array_array_flip
  • 原文地址:https://www.cnblogs.com/hh--boke/p/15320008.html
Copyright © 2020-2023  润新知