「模板」 可持久化平衡树

「模板」 可持久化平衡树


(There's suddenly something wrong with my Chinese Input Method...)

Persistable FHQ_Treap.

MLE 2 points after debugging for a whole evening for the pointers.

At last I chose to use array.

Although AC, upset.

#include <climits>
#include <cstdio>
#include <cstdlib>
const int MAXN=500010;
int n;
class FHQ_Treap
{
    public:
        FHQ_Treap(void):cnt(0)
        {
            rt[0]=0;
        }
        void Copy(int i,int j)
        {
            rt[i]=rt[j];
        }
        void Insert(int i,int x)
        {
            int l,r,t=NewNode(x);
            Split(rt[i],x,l,r);
            Merge(l,l,t);
            Merge(rt[i],l,r);
        }
        void Delete(int i,int x)
        {
            int l,r,t;
            Split(rt[i],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[i],l,r);
        }
        void Rank(int i,int x)
        {
            int l,r;
            Split(rt[i],x-1,l,r);
            printf("%d\n",s[l].size+1);
            Merge(rt[i],l,r);
        }
        void Find(int i,int x)
        {
            printf("%d\n",FindKth(rt[i],x));
        }
        void Prev(int i,int x)
        {
            int l,r;
            Split(rt[i],x-1,l,r);
            printf("%d\n",FindKth(l,s[l].size));
            Merge(rt[i],l,r);
        }
        void Next(int i,int x)
        {
            int l,r;
            Split(rt[i],x,l,r);
            printf("%d\n",FindKth(r,1));
            Merge(rt[i],l,r);
        }
    private:
        int cnt,rt[MAXN];
        struct Node
        {
            int v,p,size,c[2];
            Node(int v=0,int p=0,int size=0):v(v),p(p),size(size)
            {
                c[0]=c[1]=0;
            }
        }s[MAXN*50];
        void Update(int i)
        {
            s[i].size=s[s[i].c[0]].size+s[s[i].c[1]].size+1;
        }
        int NewNode(int x)
        {
            s[++cnt]=Node(x,rand(),1);
            return cnt;
        }
        void Split(int i,int x,int &l,int &r)
        {
            if(!i)
            {
                l=r=0;
                return;
            }
            if(x<s[i].v)
            {
                r=++cnt;
                s[r]=s[i];
                Split(s[r].c[0],x,l,s[r].c[0]);
                Update(r);
            }
            else
            {
                l=++cnt;
                s[l]=s[i];
                Split(s[l].c[1],x,s[l].c[1],r);
                Update(l);
            }
        }
        void Merge(int &i,int l,int r)
        {
            if(!l || !r)
            {
                i=l|r;
                return;
            }
            i=++cnt;
            if(s[l].p>s[r].p)
            {
                i=r;
                Merge(s[r].c[0],l,s[r].c[0]);
            }
            else
            {
                i=l;
                Merge(s[l].c[1],s[l].c[1],r);
            }
            Update(i);
        }
        int FindKth(int i,int x)
        {
            int t;
            while(x^(t=s[s[i].c[0]].size+1))
                if(x>t)
                    x-=t,i=s[i].c[1];
                else
                    i=s[i].c[0];
            return s[i].v;
        }
}*T=new FHQ_Treap;
int main(int argc,char** argv)
{
    scanf("%d",&n);
    for(int i=1,j,opt,x;i<=n;++i)
    {
        scanf("%d %d %d",&j,&opt,&x);
        T->Copy(i,j);
        switch(opt)
        {
            case 1:
                T->Insert(i,x);
                break;
            case 2:
                T->Delete(i,x);
                break;
            case 3:
                T->Rank(i,x);
                break;
            case 4:
                T->Find(i,x);
                break;
            case 5:
                T->Prev(i,x);
                break;
            case 6:
                T->Next(i,x);
                break;
        }
    }
    delete T;
    return 0;
}

Thanks for reading.

转载于:https://www.cnblogs.com/Capella/p/9053681.html

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值