首页 > 其他 > 详细

【模板】普通平衡树(splay)

时间:2020-01-31 11:26:51      阅读:83      评论:0      收藏:0      [点我收藏+]

安利splay讲解:

[洛谷日报第62期]Splay简易教程

【模板】普通平衡树(luogu)

Description

 

题目描述

 

您需要写一种数据结构(可参考题目标题),来维护一些数,其中需要提供以下操作:

  1. 插入 xx 数
  2. 删除 xx 数(若有多个相同的数,因只删除一个)
  3. 查询 xx 数的排名(排名定义为比当前数小的数的个数 +1+1 )
  4. 查询排名为 xx 的数
  5. 求 xx 的前驱(前驱定义为小于 xx,且最大的数)
  6. 求 xx 的后继(后继定义为大于 xx,且最小的数)

 

输入格式

 

第一行为 nn,表示操作的个数,下面 nn 行每行有两个数 \text{opt}opt 和 xx,\text{opt}opt 表示操作的序号( 1 \leq \text{opt} \leq 61opt6 )

 

输出格式

 

对于操作 3,4,5,63,4,5,6 每行输出一个数,表示对应答案

Code

#include <iostream>
using namespace std;
const int N=1e5+10;
//1:插入xx数
//2:删除xx数(若有多个相同的数,因只删除一个)
//3:查询xx数的排名(排名定义为比当前数小的数的个数+1。若有多个相同的数,因输出最小的排名)
//4:查询排名为xx的数
//5:求xx的前驱(前驱定义为小于xx,且最大的数)
//6:求xx的后继(后继定义为大于xx,且最小的数)
int n,x,opt,cnt[N],size[N],val[N],tot,ch[N][2],rt,fa[N];
struct Splay
{
    void push_up(int x)
    {
        size[x]=size[ch[x][0]]+size[ch[x][1]]+cnt[x];
    }
    bool get(int x)
    {
        return x==ch[fa[x]][1];
    }
    void clear(int x)
    {
        size[x]=ch[x][0]=ch[x][1]=cnt[x]=val[x]=fa[x]=0;
    }
    void rotate(int x)
    {
        int y=fa[x],z=fa[y],wh=get(x);
        fa[ch[x][wh^1]]=y;
        ch[y][wh]=ch[x][wh^1];
        ch[x][wh^1]=y;
        fa[x]=z,fa[y]=x;
        if(z) ch[z][y==ch[z][1]]=x;
        push_up(y),push_up(x); 
    }
    void splay(int x)
    {
        for(int f=fa[x];f=fa[x],f;rotate(x))
            if(fa[f]) rotate(get(f)==get(x)?f:x);
        rt=x;
    }
    int nxt()
    {
        int now=ch[rt][1];
        while(ch[now][0]) now=ch[now][0];
        return now;
    }
    int pre()
    {
        int now=ch[rt][0];
        while(ch[now][1]) now=ch[now][1];
        return now;
    }
    int rk(int x)
    {
        int res=0,now=rt;
        while(1)
        {
            if(x<val[now]) now=ch[now][0];
            else
            {
                res+=size[ch[now][0]];
                if(x==val[now])
                {
                    splay(now);
                    return res+1;
                }
                res+=cnt[now],now=ch[now][1];
            }
        }
    }
    int kth(int x)
    {
        int now=rt;
        while(1)
        {
            if(ch[now][0] && x<=size[ch[now][0]]) now=ch[now][0];
            else
            {
                x-=size[ch[now][0]]+cnt[now];
                if(x<=0) return val[now];
                now=ch[now][1];
            }
        }    
    }
    void ins(int x)
    {
        if(!rt)
        {
            rt=++tot,cnt[tot]=1,val[tot]=x;
            push_up(tot);
            return ;
        }
        int now=rt,par=0;
        while(1)
        {
            if(val[now]==x)
            {
                cnt[now]++;
                push_up(now),push_up(par);
                splay(now);
                return ;
            }
            par=now,now=ch[now][x>val[now]];
            if(!now)
            {
                cnt[++tot]=1,val[tot]=x,fa[tot]=par;
                ch[par][x>val[par]]=tot;
                push_up(tot),push_up(par);
                splay(tot);
                return ;
            }
        }
    }
    void del(int x)
    {
        rk(x);
        if(cnt[rt]>1) cnt[rt]--,push_up(rt);
        else if(!ch[rt][0] && !ch[rt][1]) clear(rt),rt=0;
        else if(!ch[rt][0])
        {
            int now=rt;
            rt=ch[rt][1],fa[rt]=0;
            clear(now);
        }
        else if(!ch[rt][1])
        {
            int now=rt;
            rt=ch[rt][0],fa[rt]=0;
            clear(now);
        }
        else
        {
            int x=pre(),now=rt;
            splay(x);
            fa[ch[now][1]]=rt;
            ch[rt][1]=ch[now][1];
            clear(now);
            push_up(rt);
        }
    }
}tree;
int main()
{
    ios::sync_with_stdio(false);
    cin>>n;
    while(n--)
    {
        cin>>opt>>x;
        if(opt==1) tree.ins(x);
        else if(opt==2) tree.del(x);
        else if(opt==3) cout<<tree.rk(x)<<endl;
        else if(opt==4) cout<<tree.kth(x)<<endl;
        else if(opt==5) tree.ins(x),cout<<val[tree.pre()]<<endl,tree.del(x);
        else if(opt==6) tree.ins(x),cout<<val[tree.nxt()]<<endl,tree.del(x);
    }
    return 0;
}

 

 

【模板】普通平衡树(splay)

原文:https://www.cnblogs.com/hsez-cyx/p/12244736.html

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!