【bzoj3224】Splay模板

本文提供了一个Splay树的数据结构实现模板,详细介绍了Splay树的各种操作如插入、删除、查找等,并通过一个完整的C++代码示例展示了如何在实际应用中使用Splay树。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

借着这道题贴一下splay的模板,自己的splay是照着油田的ZYF学的,跟她写的差不多,但是好慢(不要被dalao看到),不过其实蛮精炼的(什么鬼),感觉没有那么多的废话,贴代码跑

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<string>
#include<queue>

using namespace std;
const int N=100010;
int n;
inline int F()
{
    register int aa,bb;register char ch;
    while(ch=getchar(),ch!='-'&&(ch>'9'||ch<'0'));ch=='-'?aa=bb=0:(aa=ch-'0',bb=1);
    while(ch=getchar(),ch>='0'&&ch<='9')aa=(aa<<3)+(aa<<1)+ch-'0';return bb?aa:-aa;
}
struct SplayTree{
    int ch[N][2],f[N],size[N],cnt[N],key[N];
    int sz,root;
inline  void clear(int x){ch[x][1]=ch[x][0]=size[x]=f[x]=key[x]=cnt[x]=0;}
inline  bool get(int x){return ch[f[x]][1]==x;}
inline  void updata(int x)
    {
        if (x)
        {
            size[x]=cnt[x];
            if (ch[x][0])size[x]+=size[ch[x][0]];
            if (ch[x][1])size[x]+=size[ch[x][1]];
        }
    }
inline  void rotate(int x)
    {
        int old=f[x],oldf=f[old],which=get(x);
        ch[old][which]=ch[x][which^1];f[ch[old][which]]=old;
        f[old]=x;ch[x][which^1]=old;f[x]=oldf;
        if (oldf)
            ch[oldf][ch[oldf][1]==old]=x;
        updata(x);updata(old);
    }
inline  void splay(int x)
    {
        for (int fa;(fa=f[x]);rotate(x))
        if (f[fa])rotate((get(x)==get(fa))?fa:x);
        root=x;
    }
inline  void insert(int v)
    {
        if (root==0)
        {
            sz++;ch[sz][0]=ch[sz][1]=f[sz]=0;
            key[sz]=v;size[sz]=1;cnt[sz]=1;
            root=sz;return;
        }
        int now=root,fa=0;
        while(1)
        {
            if (key[now]==v)
            {
                cnt[now]++;updata(now);updata(fa);
                splay(now);break;
            }
            fa=now;now=ch[now][key[now]<v];
            if (now==0)
            {
                sz++;
                ch[sz][0]=ch[sz][1]=0;key[sz]=v;
                size[sz]=1;cnt[sz]=1;f[sz]=fa;
                ch[fa][key[fa]<v]=sz;
                updata(fa);splay(sz);break;
            }
        }
    }
inline  int find(int v)
    {
        int ans=0,now=root;
        while(1)
        {
            if (v<key[now])now=ch[now][0];
            else 
            {
                ans+=(ch[now][0]?size[ch[now][0]]:0);
                if (v==key[now]){splay(now);return ans+1;}
                ans+=cnt[now];now=ch[now][1];
            }
        }
    }
inline  int findx(int x)
    {
        int now=root;
        while (1)
        {
            if (ch[now][0]&&x<=size[ch[now][0]])
            now=ch[now][0];
            else 
            {
                int temp=(ch[now][0]?size[ch[now][0]]:0)+cnt[now];
                if (x<=temp)return key[now];
                x-=temp;now=ch[now][1];
            }
        }
    }
inline  int pre()
    {
        int now=ch[root][0];
        while (ch[now][1])now=ch[now][1];
        return now;
    }
inline  int suc()
    {
        int now=ch[root][1];
        while(ch[now][0])now=ch[now][0];
        return now;
    }
inline  void del(int x)
    {
        int whatever=find(x);
        if (cnt[root]>1){cnt[root]--;updata(root);return;}
        if (!ch[root][0]&&!ch[root][1]){clear(root);root=0;return;}
        if (!ch[root][0])
        {
            int oldroot=root;root=ch[root][1];f[root]=0;clear(oldroot);return;
        }
        if (!ch[root][1])
        {
            int oldroot=root;root=ch[root][0];f[root]=0;clear(oldroot);return;
        }
        int leftbig=pre(),oldroot=root;
        splay(leftbig);
        f[ch[oldroot][1]]=root;
        ch[root][1]=ch[oldroot][1];
        clear(oldroot);
        updata(root);
        return;
    }
inline  int head(int x)
    {
        insert(x);int p=key[pre()];del(x);return p;
    }
inline  int next(int x)
    {
        insert(x);int p=key[suc()];del(x);return p;
    }
}T;
int main()
{
//  freopen("std.in","r",stdin);
    int opt,opx;
    n=F();T.sz=0;
    while(n--)
    {
//      cout<<n<<endl;
        opt=F(),opx=F();
        if (opt==1)T.insert (opx);
        else if (opt==2)T.del(opx);
        else if (opt==3)printf("%d\n",T.find(opx));
        else if (opt==4)printf("%d\n",T.findx(opx));
        else if (opt==5)printf("%d\n",T.head(opx));
        else if (opt==6)printf("%d\n",T.next(opx));
//      for (int i=1;i<=T.sz;i++)
//      cout<<T.key[i]<<' ';
//      cout<<endl;
    }
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值