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;
}
原文地址:https://www.cnblogs.com/hh--boke/p/15320008.html