题解【可持久化平衡树】

\[ Preface \]

莫得 Preface 。
\[ Description \]
【普通平衡树】的可持久化版本。
\[ Solution \]
我们知道 \(\text{fhq treap}\) 是资瓷可持久化的。

重点就在于 \(\text{fhq treap}\) 的核心操作 \(split\)\(merge\) 上,这两个操作改变了 \(\text{fhq treap}\) 的形态。

那也就是说我们在 \(split\)\(merge\) 的时候,新建立节点,将原节点的信息赋给新节点,再进行操作,使得当前版本的 \(\text{fhq treap}\) 不影响到之前版本的 \(\text{fhq treap}\) ,就达到了可持久化的目的。

split

void split_v(int p,int val,int &x,int &y)
{
    if(!p)
        x=y=0;
    else
    {
        if(t[p].val<=val)
        {
            x=++tot,t[x]=t[p];
            split_v(t[x].rc,val,t[x].rc,y),upd(x);
        }
        else
        {
            y=++tot,t[y]=t[p];
            split_v(t[y].lc,val,x,t[y].lc),upd(y);
        }
    }
}

merge

int merge(int p,int q)
{
    if(!p||!q)
        return p^q;
    else
    {
        int now=++tot;
        if(t[p].dat>t[q].dat)
            t[now]=t[p],t[now].rc=merge(t[now].rc,q);
        else
            t[now]=t[q],t[now].lc=merge(p,t[now].lc);
        upd(now);
        return now;
    }
}

但实际上 \(insert\)\(remove\) 的时候,我们在 \(split\) 的过程中已经完成了新建节点这一步,就没必要在 \(merge\) 的时候再多新建节点而保留那两棵要合并的树了。

剩下的操作只要复读复读复读就行了,或者说按有旋 \(\text{treap}\) 一样的方式做。

时空复杂度 \(Θ(n \log n)\)
\[ Code \]

#include
#include

#define RI register int

using namespace std;

inline int read()
{
    int x=0,f=1;char s=getchar();
    while(s<'0'||s>'9'){if(s=='-')f=-f;s=getchar();}
    while(s>='0'&&s<='9'){x=x*10+s-'0';s=getchar();}
    return x*f;
}

const int N=500100,MLOGN=30001000;

const int INF=2147483647;

int m;

int tot,root[N];
struct treap{
    int lc,rc;
    int val,dat;
    int size;
}t[MLOGN];

int New(int val)
{
    tot++;
    t[tot].lc=t[tot].rc=0;
    t[tot].val=val,t[tot].dat=rand();
    t[tot].size=1;
    return tot; 
}

void upd(int p)
{
    t[p].size=t[t[p].lc].size+t[t[p].rc].size+1;
}

void split_v(int p,int val,int &x,int &y)
{
    if(!p)
        x=y=0;
    else
    {
        if(t[p].val<=val)
        {
            x=++tot,t[x]=t[p];
            split_v(t[x].rc,val,t[x].rc,y),upd(x);
        }
        else
        {
            y=++tot,t[y]=t[p];
            split_v(t[y].lc,val,x,t[y].lc),upd(y);
        }
    }
}

int merge(int p,int q)
{
    if(!p||!q)
        return p^q;
    if(t[p].dat>t[q].dat)
    {
        t[p].rc=merge(t[p].rc,q),upd(p);
        return p;
    }
    else
    {
        t[q].lc=merge(p,t[q].lc),upd(q);
        return q;
    }
}

int x,y,z;

void insert(int &rt,int val)
{
    split_v(rt,val-1,x,y);
    rt=New(val);
    rt=merge(x,rt);
    rt=merge(rt,y);
}

void remove(int &rt,int val)
{
    split_v(rt,val-1,x,y);
    split_v(y,val,y,z);
    y=merge(t[y].lc,t[y].rc);
    rt=merge(x,y);
    rt=merge(rt,z);
}

int GetValByRank(int p,int rank)
{
    if(!p)
        return INF;
    if(rank<=t[t[p].lc].size)
        return GetValByRank(t[p].lc,rank);
    if(rank==t[t[p].lc].size+1)
        return t[p].val;
    if(t[t[p].lc].size0)
            {
                p=t[p].lc;
                while(t[p].rc>0)p=t[p].rc;
                ans=t[p].val;
            }
            break;
        }
        if(t[p].valans)ans=t[p].val;
        p=val0)
            {
                p=t[p].rc;
                while(t[p].lc>0)p=t[p].lc;
                ans=t[p].val;
            }
            break;
        }
        if(t[p].val>val&&t[p].val

\[ Thanks \ for \ watching \]

你可能感兴趣的:(题解【可持久化平衡树】)