Splay模板

Posted milk-feng

tags:

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

#include<iostream>
#include<cstring>
#include<cstdio>
#define Reg register
#define INF 0x7ffffff
using namespace std;
int size,n,root;
struct Tree int ch[2],val,cnt,size,fat; tree[1000050];
int GetFat(int x)

    return tree[tree[x].fat].ch[1]==x;

void Update(int x)

    tree[x].size=tree[tree[x].ch[0]].size+tree[tree[x].ch[1]].size+tree[x].cnt;
    return;

void Rotate(int x)

    int y=tree[x].fat;
    int z=tree[y].fat;
    int k=GetFat(x);    //先定义k 
    //x.rch-->y.lch
    tree[y].ch[GetFat(x)]=tree[x].ch[k^1];
    tree[tree[y].ch[k]].fat=y;
    //x-->z
    tree[z].ch[GetFat(y)]=x;
    tree[x].fat=z;
    //y-->x
    tree[x].ch[k^1]=y;
    tree[y].fat=x;
    Update(y); Update(x);
    //注意顺序 
    return;

void Splay(int x,int goal)

    while(tree[x].fat!=goal)
    
        int y=tree[x].fat,z=tree[y].fat;
        if(z!=goal)
        
            if(GetFat(y)==GetFat(x)) Rotate(y);
            else Rotate(x);
        
        Rotate(x);
    
    if(goal==0) root=x;
    return;

void Find(int num)

    int k=root;
    while(tree[k].ch[num>tree[k].val]&&num!=tree[k].val)
        k=tree[k].ch[num>tree[k].val];
    Splay(k,0);
    return;

int GetPre(int num)

    Find(num);
    if(tree[root].val<num) return root;
    int k=tree[root].ch[0];
    while(tree[k].ch[1]) k=tree[k].ch[1];
    return k;

int GetNext(int num)

    Find(num);
    if(tree[root].val>num) return root;
    int k=tree[root].ch[1];
    while(tree[k].ch[0]) k=tree[k].ch[0];
    return k;

void Insert(int num)

    int k=root,p=0;
    //Get position
    while(k&&tree[k].val!=num)
    
        p=k;                              //father
        k=tree[k].ch[num>tree[k].val];
    
    if(k) ++tree[k].cnt;
    else
    
        k=++size;
        if(p) tree[p].ch[num>tree[p].val]=k;  //接上
        tree[k].ch[0]=tree[k].ch[1]=0;
        tree[k].fat=p; tree[k].val=num;
        tree[k].cnt=tree[k].size=1;
    
    Splay(k,0); //update & 转到根
    return;

void Delete(int num)

    int last=GetPre(num),next=GetNext(num);
    Splay(last,0); Splay(next,root);
    //root‘s rch‘s lch =num & 没有儿子 
    int del=tree[next].ch[0];
    if(tree[del].cnt>1)   //直接减 
    
        --tree[del].cnt;
        Splay(del,0);
    
    else tree[next].ch[0]=0;
    return; 

int GetVal(int num)

    int k=root;
    while(1)
    
        if(tree[k].ch[0]&&num<=tree[tree[k].ch[0]].size)  //在左儿子 
            k=tree[k].ch[0];
        else if(num>tree[tree[k].ch[0]].size+tree[k].cnt) //在右儿子
        
            num-=(tree[tree[k].ch[0]].size+tree[k].cnt);  //注意顺序 
            k=tree[k].ch[1];
        
        else return k;  //在根节点 
    

int GetRank(int num)

    Find(num);
    return tree[tree[root].ch[0]].size;   //之前Insert了1个极小数 

int main()

    scanf("%d",&n);
    Insert(INF);
    Insert(-INF);  //为了减少时间 
    for(Reg int i=1,x,y;i<=n;++i)
    
        scanf("%d%d",&x,&y);
        if(x==1) Insert(y);
        else if(x==2) Delete(y);
        else if(x==3) printf("%d\n",GetRank(y));
        else if(x==4) printf("%d\n",tree[GetVal(y+1)].val); //排除极小值 
        else if(x==5) printf("%d\n",tree[GetPre(y)].val);
        else printf("%d\n",tree[GetNext(y)].val);
    
    return 0; 

 

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

bzoj 1588 splay模板题

P3369 模板普通平衡树 题解(Splay)

[模板]洛谷T2042 NOI2005 维护数列 Splay

[模板]洛谷T3380 二逼平衡树 线段树套Splay

「Splay」指针版与数组版模板

[模板]洛谷T3391 文艺平衡树 链表&递归版无父指针版Splay