Splay Tree模板

Posted aemshana

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Splay Tree模板相关的知识,希望对你有一定的参考价值。

#include <iostream>
#include <algorithm>
#include <cstring>
#include <cstdio>
using namespace std;

#define RG register int
#define LL long long

template<typename elemType>
inline void Read(elemType &T){
    elemType X=0,w=0; char ch=0;
    while(!isdigit(ch)) {w|=ch==‘-‘;ch=getchar();}
    while(isdigit(ch)) X=(X<<3)+(X<<1)+(ch^48),ch=getchar();
    T=(w?-X:X);
}

namespace Splay{
    template<typename elemType>
    struct SplayTreeNode{
        SplayTreeNode():fa(0),size(0),rev(0){son[0]=son[1]=0;}
        elemType value;
        int son[2],fa,size,rev;
        int &operator[](int x){return son[x];}//重载[],方便取左右儿子
    };

    template<typename elemType>
    struct SplayTree{
        SplayTreeNode<elemType> T[100010];
        int root,cnt,node_num;

        SplayTree():root(0),cnt(0),node_num(0) {}
        int size(){return node_num;}
        bool empty(){return node_num==0;}
        void push_up(int x){//上传标记
            if(x){ T[x].size=T[T[x][0]].size+T[T[x][1]].size+1;}
        }
        void push_down(int x){//下放标记
            if(!x || !T[x].rev) return;
            T[T[x][0]].rev^=1;T[T[x][1]].rev^=1;
            swap(T[x][0],T[x][1]);
            T[x].rev=0;
        }
        void rotate(int x){
            push_down(x);
            int y=T[x].fa;
            if(y==0) return;
            int a=(T[y][0]==x)?1:0;//a=0:左旋,a=1:右旋
            T[x].fa=T[y].fa;
            if(T[T[x].fa][0]==y) T[T[x].fa][0]=x;
            else T[T[x].fa][1]=x;
            T[T[x][a]].fa=y;
            T[y][1^a]=T[x][a];
            T[y].fa=x;T[x][a]=y;
            push_up(y);push_up(x);
        }
        void splay(int x,int s){//把x旋转到s
            if(x==0) return;
            int sf=T[s].fa,y,z;
            while(T[x].fa!=sf){
                y=T[x].fa;z=T[y].fa;
                if(z==sf) rotate(x);
                else{
                    if(T[y][0]==x && T[z][0]==y){rotate(y);rotate(x);}
                    else if(T[y][1]==x && T[z][1]==y){rotate(y);rotate(x);}
                    else if(T[y][0]==x && T[z][1]==y){rotate(x);rotate(x);}
                    else{rotate(x);rotate(x);}
                }
            }
            if(s==root) root=x;
            return;
        }
        void insert_node(int x,int u){
            if(x==0) return;//error
            if(T[u].value<T[x].value){
                if(T[x][0]==0){T[x][0]=u;T[u].fa=x;return;}
                else insert_node(T[x][0],u);
            }else{
                if(T[x][1]==0){T[x][1]=u;T[u].fa=x;return;}
                else insert_node(T[x][1],u);
            }
            push_up(x);
        }
        void insert(elemType val){//插入val
            T[++cnt].value=val;T[cnt].size=1;++node_num;
            if(root==0){root=cnt;return;}
            else{insert_node(root,cnt);splay(cnt,root);}
        }
        int get_previous(int x,elemType val){
            if(x==0) return 0;
            push_down(x);
            if(T[x].value<val){
                if(T[x][1]==0) return x;
                int temp=get_previous(T[x][1],val);
                return (temp==0)?x:temp;
            }else{
                if(T[x][0]==0) return 0;//not find
                return get_previous(T[x][0],val);
            }
            return 0;//error
        }
        int get_succeed(int x,elemType val){
            if(x==0) return 0;
            push_down(x);
            if(T[x].value>val){
                if(T[x][0]==0) return x;
                int temp=get_succeed(T[x][0],val);
                return (temp==0)?x:temp;
            }else{
                if(T[x][1]==0) return 0;//not find
                return get_succeed(T[x][1],val);
            }
            return 0;//error
        }
        int get_kth(int x,int Kth){
            if(x==0||Kth>T[T[x][0]].size+T[T[x][1]].size+1) return 0;//not find
            push_down(x);
            if(Kth==T[T[x][0]].size+1) return x;
            else if(Kth<=T[T[x][0]].size) return get_kth(T[x][0],Kth);
            return get_kth(T[x][1],Kth-T[T[x][0]].size-1);
        }
        int get_rank(int x,elemType val){
            if(x==0) return 1;
            push_down(x);
            if(T[x].value<val) return T[T[x][0]].size+1+get_rank(T[x][1],val);
            else return get_rank(T[x][0],val);
            return 0;//error
        }
        int find(int x,elemType val){
            if(x==0) return 0;//not find
            if(T[x].value==val) return x;
            else if(T[x].value<val) return find(T[x][1],val);
            else return find(T[x][0],val);
            return 0;//error
        }
        void traversal(int x){//中序遍历SplayTree
            if(x==0) return;
            traversal(T[x][0]);
            cout<<T[x].value<<" ";
            traversal(T[x][1]);
        }
        void delete_node(elemType val){
            int u=find(root,val);
            if(u==0) return;//not find
            splay(u,root);
            int x=T[u][0],y=get_kth(T[u][1],1);
            if(y==0){T[x].fa=0;root=x;return;}
            splay(y,T[u][1]);
            T[y][0]=x;T[y].fa=0;root=y;
            if(x!=0)T[x].fa=y;
            push_up(y);
        }
        int rank(elemType val){int res=get_rank(root,val);splay(find(root,val),root);return res;}
        int kth(int k){int u=get_kth(root,k);splay(u,root);return u;}
        int previous(elemType val){int u=get_previous(root,val);splay(u,root);return u;}
        int succeed(elemType val){int u=get_succeed(root,val);splay(u,root);return u;}
    };
};

Splay::SplayTree<int> Tree;
int Data[100];
int N;

int main(){
    Read(N);
    for(RG i=1;i<=N;++i){
        int opt,num;
        Read(opt);Read(num);
        if(opt==1) Tree.insert(num);
        else if(opt==2) Tree.delete_node(num);
        else if(opt==3) printf("%d
",Tree.rank(num));
        else if(opt==4) printf("%d
",Tree.T[Tree.kth(num)].value);
        else if(opt==5) printf("%d
",Tree.T[Tree.previous(num)].value);
        else if(opt==6) printf("%d
",Tree.T[Tree.succeed(num)].value);
    }
    return 0;
}

以上是关于Splay Tree模板的主要内容,如果未能解决你的问题,请参考以下文章

Splay_Tree 模板(区间修改,旋转操作)

手打 splay_tree 模板类 支持 find, rank, 前驱后继, iterator

splay tree旋转操作 hdu 1890

P3690 模板Link Cut Tree (动态树)

Splay模板

[知识点]Splay tree指针实现