1. 程式人生 > >SPlay 板子

SPlay 板子

#include<stdio.h>
#include<string.h>
#include<vector>
using namespace std;
typedef long long ll;
const int maxn=1e6+7;
const int N=120005,INF=0x3f3f3f3f;

struct Splay_Tree
{
    struct Node
    {
        int val,Max,add,Size,son[2];
        bool rev;
        void init(int _val)
        {
            val=Max=_val,Size=1;
            add=rev=son[0]=son[1]=0;
        }
    } T[N];
    int fa[N],root,tot;

    /*void pushDown(int x)///下放標記(序列操作)
    {
        if(x==0)return ;
        if(T[x].add)
        {
            if(T[x].son[0])
            {
                T[T[x].son[0]].val+=T[x].add;
                T[T[x].son[0]].Max+=T[x].add;
                T[T[x].son[0]].add+=T[x].add;
            }
            if(T[x].son[1])
            {
                T[T[x].son[1]].val+=T[x].add;
                T[T[x].son[1]].Max+=T[x].add;
                T[T[x].son[1]].add+=T[x].add;
            }
            T[x].add=0;
        }
        if(T[x].rev)
        {
            if(T[x].son[0])T[T[x].son[0]].rev^=1;
            if(T[x].son[1])T[T[x].son[1]].rev^=1;
            swap(T[x].son[0],T[x].son[1]);
            T[x].rev=0;
        }
    }*/

    /*void pushUp(int x)///更新節點(序列操作)
    {
        T[x].Max=T[x].val,T[x].Size=1;
        if(T[x].son[0])
        {
            T[x].Max=max(T[x].Max,T[T[x].son[0]].Max);
            T[x].Size+=T[T[x].son[0]].Size;
        }
        if(T[x].son[1])
        {
            T[x].Max=max(T[x].Max,T[T[x].son[1]].Max);
            T[x].Size+=T[T[x].son[1]].Size;
        }
    }*/

    inline void up(int x)///更新節點(普通平衡樹操作)
    {
        T[x].Size=1;
        if(T[x].son[0])
            T[x].Size+=T[T[x].son[0]].Size;
        if(T[x].son[1])
            T[x].Size+=T[T[x].son[1]].Size;
    }

    void Rotate(int x,int kind)///旋轉,有左旋右旋(反正配合splay用就好了233)
    {
        int y=fa[x],z=fa[y];
        T[y].son[!kind]=T[x].son[kind],fa[T[x].son[kind]]=y;
        T[x].son[kind]=y,fa[y]=x;
        T[z].son[T[z].son[1]==y]=x,fa[x]=z;
        up(y);
    }

    void Splay(int x,int goal)///把下標為x的元素旋轉到目標的兒子節點
    {
        if(x==goal)return ;
        while(fa[x]!=goal)
        {
            int y=fa[x],z=fa[y];
            //pushDown(z),pushDown(y),pushDown(x);
            int rx=T[y].son[0]==x,ry=T[z].son[0]==y;
            if(z==goal)Rotate(x,rx);
            else
            {
                if(rx==ry)Rotate(y,ry);
                else Rotate(x,rx);
                Rotate(x,ry);
            }
        }
        up(x);
        if(goal==0)root=x;
    }

    int Select(int pos)///查詢第k小元素
    {
        int u=root;
        //pushDown(u);
        while(T[T[u].son[0]].Size!=pos)
        {
            if(pos<T[T[u].son[0]].Size)u=T[u].son[0];
            else
            {
                pos-=T[T[u].son[0]].Size+1;
                u=T[u].son[1];
            }
            //pushDown(u);
        }
        Splay(u,root);
        return u;
    }

    void update(int L,int R,int val)///序列操作的區間更新
    {
        int u=Select(L-1),v=Select(R+1);
        Splay(u,0);
        Splay(v,u);
        T[T[v].son[0]].Max+=val;
        T[T[v].son[0]].val+=val;
        T[T[v].son[0]].add+=val;
    }

    void Reverse(int L,int R)///序列操作的區間翻轉
    {
        int u=Select(L-1),v=Select(R+1);
        Splay(u,0);
        Splay(v,u);
        T[T[v].son[0]].rev^=1;
    }

    int query(int L,int R)///區間操作的區間詢問
    {
        int u=Select(L-1),v=Select(R+1);
        Splay(u,0);
        Splay(v,u);
        return T[T[v].son[0]].Max;
    }

    int build(int L,int R)///區間操作建樹
    {
        if(L>R)return 0;
        if(L==R)return L;
        int mid=(L+R)>>1,sL,sR;
        T[mid].son[0]=sL=build(L,mid-1);
        T[mid].son[1]=sR=build(mid+1,R);
        fa[sL]=fa[sR]=mid;
        up(mid);
        return mid;
    }

    void init(int n)///區間操作,輸入n個元素建樹
    {
        T[0].init(-INF);
        for(int i=1,x;i<=n;i++)
        {
            scanf("%d",&x);
            T[i].init(x);
        }
        root=build(1,n),fa[root]=0;
        fa[0]=0,T[0].son[1]=root,T[0].Size=0;
    }

    void Insert(int &t,int val,int par=0)///普通平衡樹,往某個地方的下面插入元素,一般是插入根節點
    {
        if(t==0)
        {
            t=++tot;
            T[t].init(val);
            fa[t]=par;
            Splay(tot,0);
        }
        else
        {
            int cur=t;
            if(val<T[t].val)Insert(T[t].son[0],val,cur);
            //else if(val==T[t].val)return ;
            else Insert(T[t].son[1],val,cur);
            up(cur);
        }
    }

    int find(int t,int v)///普通平衡樹查詢值為v的元素
    {
        if(t==0)return 0;
        else if(T[t].val==v)
        {
            Splay(t,0);
            return t;
        }
        else if(v<T[t].val)return find(T[t].son[0],v);
        else return find(T[t].son[1],v);
    }

    ///刪除根節點元素
    void Delete()
    {
        if(!T[root].son[0])
        {
            fa[T[root].son[1]]=0;
            root=T[root].son[1];
        }
        else
        {
            int cur=T[root].son[0];
            while(T[cur].son[1])cur=T[cur].son[1];
            Splay(cur,root);
            T[cur].son[1]=T[root].son[1];
            root=cur,fa[cur]=0,fa[T[root].son[1]]=root;
            up(root);
        }
    }

    int size()
    {
        return T[root].Size;
    }

    ///從t開始找值為v的前驅,返回值
    int pred(int t,int v)
    {
        if(t==0)return v;
        else
        {
            if(v<=T[t].val)return pred(T[t].son[0],v);
            else
            {
                int ans=pred(T[t].son[1],v);
                if(ans==v)
                    ans=T[t].val,Splay(t,0);
                return ans;
            }
        }
    }
    ///查詢下標t節點的前驅返回下標
    int pred(int t)
    {
        Splay(t,0);
        int u=T[t].son[0];
        if(u==0)return fa[t];
        while(T[u].son[1])u=T[u].son[1];
        return u;
    }

    ///從t開始找值為v的後繼,返回值
    int succ(int t,int v)
    {
        if(t==0)return v;
        else
        {
            if(v>=T[t].val)return succ(T[t].son[1],v);
            else
            {
                int ans=succ(T[t].son[0],v);
                if(ans==v)
                    ans=T[t].val,Splay(t,0);
                return ans;
            }
        }
    }

    ///查詢下標t節點的後繼返回下標
    int succ(int t)
    {
        Splay(t,0);
        int u=T[t].son[1];
        if(u==0)return fa[t];
        while(T[u].son[0])u=T[u].son[0];
        return u;
    }

    void Preorder( int t ){///輸出成序列順便檢查是否有邏輯錯誤
        if( !t ) return;
        Preorder( T[t].son[0] );
        if(T[t].son[0]&&fa[T[t].son[0]]!=t)
            printf("!");
        printf("%d " , T[t].val );
        Preorder( T[t].son[1] );
    }

    void init()///普通平衡樹初始化
    {
        T[1].init(-INF);
        tot=root=1;
    }

    void update(int x)///更新下標為x的節點。。手動操作後呼叫
    {
        while(x!=0)
        up(x),x=fa[x];
    }

};