「模板」 FHQ_Treap

Posted Capella

tags:

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

「模板」 FHQ_Treap

<题目链接>


我也是偶然发现我还没发过FHQ_Treap的板子。

那就发一波吧。

这个速度实在不算快,但是不用旋转,并且好写

更重要的是,Splay 可以做的事情它都可以做!比如区间操作,以及LCT相关…

而且它还可以可持久化!(虽然目前还没有学)

Capella 认为,不涉及区间操作时,用快一些的平衡树(SBT/Treap/替罪羊...)较好,涉及区间操作而又不想写大量代码的话,FHQ_Treap 不失为一种极好的选择。

下一篇写 FHQ_Treap 的区间操作。

#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <ctime>
const int MAXN=100010;
int n;
class FHQ_Treap
{
    public:
        int rt;
        FHQ_Treap(void)
        {
            rt=cnt=0;
            memset(a,0,sizeof a);
            memset(s,0,sizeof s);
        }
        void Insert(int x)
        {
            int l=0,r=0,t=0;
            MakeNode(t,x),Split(rt,x,l,r);
            Merge(l,l,t),Merge(rt,l,r);
        }
        void Erase(int x)
        {
            int l=0,r=0,t=0;
            Split(rt,x,l,r),Split(l,x-1,l,t);
            Merge(t,s[t].c[0],s[t].c[1]),Merge(l,l,t),Merge(rt,l,r);
        }
        int Rank(int x)
        {
            int l=0,r=0,ans;
            Split(rt,x-1,l,r),ans=s[l].size+1,Merge(rt,l,r);
            return ans;
        }
        int Find(int i,int x)
        {
            int t;
            while(x!=(t=s[s[i].c[0]].size+1))
                if(x<t)
                    i=s[i].c[0];
                else
                    x-=t,i=s[i].c[1];
            return s[i].v;
        }
        int Pre(int x)
        {
            int l=0,r=0,ans;
            Split(rt,x-1,l,r),ans=Find(l,s[l].size),Merge(rt,l,r);
            return ans;
        }
        int Next(int x)
        {
            int l=0,r=0,ans;
            Split(rt,x,l,r),ans=Find(r,1),Merge(rt,l,r);
            return ans;
        }
    private:
        bool a[MAXN];
        int cnt;
        struct node
        {
            int v,p,size,c[2];
        }s[MAXN];
        int Random(void)
        {
            int x;
            while(a[x=rand()%MAXN]);
            a[x]=1;
            return x;
        }
        void Update(int i)
        {
            s[i].size=s[s[i].c[0]].size+s[s[i].c[1]].size+1;
        }
        void MakeNode(int &i,int x)
        {
            s[i=++cnt].v=x,s[i].p=Random(),s[i].size=1;
        }
        void Split(int i,int x,int &l,int &r)
        {
            if(!i)
            {
                l=r=0;
                return;
            }
            else if(x<s[i].v)
                Split(s[r=i].c[0],x,l,s[i].c[0]);
            else
                Split(s[l=i].c[1],x,s[i].c[1],r);
            Update(i);
        }
        void Merge(int &i,int l,int r)
        {
            if(!l || !r)
            {
                i=l|r;
                return;
            }
            else if(s[l].p>s[r].p)
                Merge(s[i=l].c[1],s[l].c[1],r);
            else
                Merge(s[i=r].c[0],l,s[r].c[0]);
            Update(i);
        }
}T;
int main(int argc,char *argv[])
{
    srand((unsigned)time(NULL));
    scanf("%d",&n);
    for(int i=1,opt,x;i<=n;++i)
    {
        scanf("%d %d",&opt,&x);
        switch(opt)
        {
            case 1:
                T.Insert(x);
                break;
            case 2:
                T.Erase(x);
                break;
            case 3:
                printf("%d\n",T.Rank(x));
                break;
            case 4:
                printf("%d\n",T.Find(T.rt,x));
                break;
            case 5:
                printf("%d\n",T.Pre(x));
                break;
            case 6:
                printf("%d\n",T.Next(x));
                break;
        }
    }
    return 0;
}

谢谢阅读。

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

VSCode自定义代码片段——.vue文件的模板

VSCode自定义代码片段1——vue主模板

VSCode自定义代码片段2——.vue文件的模板

VSCode自定义代码片段(vue主模板)

Eclipse 中的通用代码片段或模板

浅谈fhq_treap