平衡树SBT模板

#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
#define maxn 100005
int siz[maxn],key[maxn],L[maxn],R[maxn];
int n,rt,tot;
 
void right_rotate(int &rt)
{
    int k=L[rt];
    L[rt]=R[k];
    R[k]=rt;
    siz[k]=siz[rt];
    siz[rt]=siz[L[rt]]+siz[R[rt]]+1;
    rt=k;   
}
 
void left_rotate(int &rt)
{
    int k=R[rt];
    R[rt]=L[k];
    L[k]=rt;
    siz[k]=siz[rt];
    siz[rt]=siz[L[rt]]+siz[R[rt]]+1;
    rt=k;   
}
 
void maintain(int &rt,bool flag)
{
    if (flag==0) 
    {
        if (siz[L[L[rt]]]>siz[R[rt]]) right_rotate(rt);
        else if (siz[R[L[rt]]]>siz[R[rt]])
        {
            left_rotate(L[rt]);
            right_rotate(rt);   
        }
        else return;
    }
    else
    {
        if (siz[R[R[rt]]]>siz[L[rt]]) left_rotate(rt);
        else if (siz[L[R[rt]]]>siz[L[rt]])
        {
            right_rotate(R[rt]);
            left_rotate(rt);
        }
        else return;
    }
    maintain(L[rt],0);
    maintain(R[rt],1);
    maintain(rt,1);
    maintain(rt,0);
}
 
void insert(int &rt,int v)
{
    if (rt==0) 
    {
        tot++;
        siz[tot]=1;
        key[tot]=v;
        rt=tot;
    }
    else
    {
        siz[rt]++;
        if (v<key[rt]) insert(L[rt],v);
        else insert(R[rt],v);
        maintain(rt,v>=key[rt]);     
    }
}
 
int dele(int &rt,int v)
{
    int d;
    siz[rt]--;
    if (key[rt]==v||(key[rt]<v&&R[rt]==0)||(key[rt]>v&&L[rt]==0))
    {
        d=key[rt];
        if (L[rt]==0||R[rt]==0) rt=L[rt]+R[rt];
        else key[rt]=dele(L[rt],v+1);
    }
    else
    {
        if (v>key[rt]) d=dele(R[rt],v);
        else d=dele(L[rt],v);
    }   
    return d;
}
 
int rank(int &rt,int v)
{
    int r;
    if (rt==0) return 1;
    if (v<=key[rt]) r=rank(L[rt],v);
    else r=rank(R[rt],v)+siz[L[rt]]+1;  
    return r;
}
 
int select(int &rt,int k)
{   
    int s;
    if (k<siz[L[rt]]+1) s=select(L[rt],k);
    if (k==siz[L[rt]]+1) s=key[rt]; 
    if (k>siz[L[rt]]+1) s=select(R[rt],k-siz[L[rt]]-1);
    return s;
}
 
int pred(int &rt,int v)
{
    int p;
    if (rt==0) return -1;
    if (key[rt]>=v) p=pred(L[rt],v);
    else
    {
        p=pred(R[rt],v);
        if (p==-1) p=key[rt];
    }
    return p;
}
 
int succ(int &rt,int v)
{
    int s;
    if (rt==0) return -1;
    if (key[rt]<=v) s=succ(R[rt],v);
    else
    {
        s=succ(L[rt],v);
        if (s==-1) s=key[rt];
    }
    return s;
}
 
int main()
{
    scanf("%d",&n);
    for (int i=1;i<=n;i++) 
    {
        int a,opt;
        scanf("%d%d",&opt,&a);
        if (opt==1) insert(rt,a);
        if (opt==2) dele(rt,a);
        if (opt==3) printf("%d\n",rank(rt,a));
        if (opt==4) printf("%d\n",select(rt,a));
        if (opt==5) printf("%d\n",pred(rt,a));
        if (opt==6) printf("%d\n",succ(rt,a));  
    }
    return 0;   
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值