可持久化平衡树

可持久化平衡树

对可持久化 非旋 \(Treap\) 来说:

在复制一个节点 \(X_{a}\)\(X\) 节点的第 \(a\) 个版本)的新版本 \(X_{a+1}\)\(X\) 节点的第 \(a+1\) 个版本)以后:

  • 如果某个儿子节点 \(Y\) 不用修改信息,那么就把 \(X_{a+1}\) 的指针直接指向 \(Y_{a}\)\(Y\) 节点的第 \(a\) 个版本)即可。
  • 反之,如果要修改 \(Y\),那么就在递归到下层时新建 \(Y_{a+1}\)\(Y\) 节点的第 \(a+1\) 个版本)这个新节点用于存储新的信息,同时把 \(X_{a+1}\) 的指针指向 \(Y_{a+1}\)\(Y\) 节点的第 \(a+1\) 个版本)。

可持久化普通平衡树

由于\(FHQ\) \(Treap\)中对树的形态造成影响的只有 \(Split\)\(Merge\)

\(Split\)\(Merge\) 操作都只会改变两颗 \(Treap\) 交接处的节点

而交接处的节点构成 \(Treap\) 上的一条链

所以我们可以在交接处新开点,然后其他点依次复制

要开50倍空间

\(split\)

il void split(cs int rt,cs int k,int &x,int &y){
    if(!rt) return x=y=0,void();
    if(t[rt].val<=k){
        t[x=++cnt]=t[rt];
        split(rs(x),k,rs(x),y);
        update(x);
    } 
    else{
        t[y=++cnt]=t[rt];
        split(ls(y),k,x,ls(y));
        update(y);
    } 
}

\(merge\)

il int merge(cs int x,cs int y){
    if(!x||!y) return x+y;
    ri int rt=++cnt;
    if(t[x].pri<t[y].pri){
        t[rt]=t[x];
        rs(rt)=merge(rs(rt),y);
        return update(rt),rt;
    }
    else{
        t[rt]=t[y];
        ls(rt)=merge(x,ls(rt));
        return update(rt),rt;
    }
}
code
#include <bits/stdc++.h>
#define il inline
#define cs const
#define ri register        
using namespace std;

namespace Q{
    il int rd(){
        ri int x=0;ri bool f=0;ri char c=getchar();
        while(!isdigit(c)) f|=(c==45),c=getchar();
        while(isdigit(c)) x=x*10+(c^48),c=getchar();
        return f?-x:x;
    }
    il void wt(int x){
        if(x<0) x=-x,putchar(45);
        if(x>=10) wt(x/10);
        return putchar(x%10|48),void();
    }
    il void wn(int x,char c=10){
        wt(x),putchar(c);
    }
} using namespace Q;

cs int N=5e5+5,inf=2147483647;

namespace fhq_treap{
    #define ls(x) t[x].ch[0]
    #define rs(x) t[x].ch[1]

    mt19937 srd(time(0));
    int cnt,rot[N];
    struct tree{
        int ch[2],val,pri,sz;
    }t[N*50];

    il int add(int val=0){
        t[++cnt].val=val;
        t[cnt].sz=1;
        t[cnt].pri=srd();
        return cnt;
    }

    il void update(int rt){
        t[rt].sz=t[ls(rt)].sz+t[rs(rt)].sz+1;
    }

    il int merge(cs int x,cs int y){
        if(!x||!y) return x+y;
        ri int rt=++cnt;
        if(t[x].pri<t[y].pri){
            t[rt]=t[x];
            rs(rt)=merge(rs(rt),y);
            return update(rt),rt;
        }
        else{
            t[rt]=t[y];
            ls(rt)=merge(x,ls(rt));
            return update(rt),rt;
        }
    }

    il void split(cs int rt,cs int k,int &x,int &y){
        if(!rt) return x=y=0,void();
        if(t[rt].val<=k){
            t[x=++cnt]=t[rt];
            split(rs(x),k,rs(x),y);
            update(x);
        } 
        else{
            t[y=++cnt]=t[rt];
            split(ls(y),k,x,ls(y));
            update(y);
        } 
    }

    il void ins(int &rt,cs int val){
        ri int x,y; split(rt,val,x,y);
        rt=merge(merge(x,add(val)),y);
    }

    il void del(int &rt,cs int val){
        ri int x,y,z; split(rt,val,x,z),split(x,val-1,x,y);
        y=merge(ls(y),rs(y)),rt=merge(merge(x,y),z);
    }

    il int rnk(int &rt,cs int val){
        ri int x,y,rk;split(rt,val-1,x,y);
        return rk=t[x].sz+1,rt=merge(x,y),rk;
    }

    il int kth(int rt,int k){
        while(1){
            if(k<=t[ls(rt)].sz) rt=ls(rt);
            else if(k==t[ls(rt)].sz+1) return rt;
            else k-=t[ls(rt)].sz+1,rt=rs(rt);
        }
    }

    il int pre(int &rt,int val){
        ri int x,y,as; split(rt,val-1,x,y);
        as=t[kth(x,t[x].sz)].val;
        return rt=merge(x,y),as;
    }

    il int nxt(int &rt,int val){
        ri int x,y,as; split(rt,val,x,y);
        as=t[kth(y,1)].val;
        return rt=merge(x,y),as;   
    }

    #undef ls
    #undef rs
} using namespace fhq_treap;

signed main(){
    ri int n=rd();
    ins(rot[0],inf),ins(rot[0],-inf);
    for(ri int i=1,op,x;i<=n;++i){
        rot[i]=rot[rd()],op=rd(),x=rd();
        switch (op){
            case 1: ins(rot[i],x); break;
            case 2: del(rot[i],x); break;
            case 3: wn(rnk(rot[i],x)-1); break;
            case 4: wn(t[kth(rot[i],x+1)].val); break;
            case 5: wn(pre(rot[i],x)); break;
            case 6: wn(nxt(rot[i],x)); break;
        }
    }
    return 0;
}

可持久化文艺平衡树

\(Split\) 过程中对要修改的结点进行复制,在新节点上修改

\(Split\)\(Merge\) 总是成对出现,只用复制一次

要看128倍空间(回收结点64倍)

\(pushdown\)

il void pushdown(int rt){
    if(t[rt].lz){
        if(ls(rt)) t[++cnt]=t[ls(rt)],ls(rt)=cnt; //
        if(rs(rt)) t[++cnt]=t[rs(rt)],rs(rt)=cnt; //
        swap(ls(rt),rs(rt)),t[rt].lz=0;
        if(ls(rt)) t[ls(rt)].lz^=1;
        if(rs(rt)) t[rs(rt)].lz^=1;
    }
}

\(split\)

il void split(cs int rt,cs int k,int &x,int &y){
    if(!rt) return x=y=0,void();
    pushdown(rt);
    if(t[ls(rt)].sz<k){
        t[x=++cnt]=t[rt];
        split(rs(x),k-t[ls(rt)].sz-1,rs(x),y);
        update(x);
    }
    else{
        t[y=++cnt]=t[rt];
        split(ls(y),k,x,ls(y));
        update(y);
    } 
}
code
#include <bits/stdc++.h>
#define il inline
#define cs const
#define ri register
#define int long long
using namespace std;

namespace Q{
    il int rd(){
        ri int x=0;ri bool f=0;ri char c=getchar();
        while(!isdigit(c)) f|=(c==45),c=getchar();
        while(isdigit(c)) x=x*10+(c^48),c=getchar();
        return f?-x:x;
    }
    il void wt(int x){
        if(x<0) x=-x,putchar(45);
        if(x>=10) wt(x/10);
        return putchar(x%10|48),void();
    }
    il void wn(int x,char c=10){
        wt(x),putchar(c);
    }
} using namespace Q;

cs int N=2e5+5;

namespace fhq_treap{
    #define ls(x) t[x].ch[0]
    #define rs(x) t[x].ch[1]

    mt19937 srd(time(0));
    int cnt,rot[N];
    struct tree{
        int ch[2],val,pri,sz,lz,sum;
    }t[N<<7];

    il int add(int val=0){
        t[++cnt].val=val,t[cnt].sum=val;
        t[cnt].sz=1,t[cnt].pri=srd();
        return cnt;
    }

    il void update(int rt){
        t[rt].sz=t[ls(rt)].sz+t[rs(rt)].sz+1;
        t[rt].sum=t[ls(rt)].sum+t[rs(rt)].sum+t[rt].val;
    }

    il void pushdown(int rt){
        if(t[rt].lz){
            if(ls(rt)) t[++cnt]=t[ls(rt)],ls(rt)=cnt; //
            if(rs(rt)) t[++cnt]=t[rs(rt)],rs(rt)=cnt; //
            swap(ls(rt),rs(rt)),t[rt].lz=0;
            if(ls(rt)) t[ls(rt)].lz^=1;
            if(rs(rt)) t[rs(rt)].lz^=1;
        }
    }

    il void split(cs int rt,cs int k,int &x,int &y){
        if(!rt) return x=y=0,void();
        pushdown(rt);
        if(t[ls(rt)].sz<k){
            t[x=++cnt]=t[rt];
            split(rs(x),k-t[ls(rt)].sz-1,rs(x),y);
            update(x);
        }
        else{
            t[y=++cnt]=t[rt];
            split(ls(y),k,x,ls(y));
            update(y);
        } 
    }

    il int merge(cs int x,cs int y){
        if(!x||!y) return x+y;
        if(t[x].pri<t[y].pri){
            pushdown(x);
            rs(x)=merge(rs(x),y);
            return update(x),x;
        }
        else{
            pushdown(y);
            ls(y)=merge(x,ls(y));
            return update(y),y;
        }
    }
    
    il void rev(int &rt,cs int l,cs int r){
        ri int x,y,z;
        split(rt,r,x,z),split(x,l-1,x,y);
        t[y].lz^=1,rt=merge(merge(x,y),z);
    }

    il int ask(int &rt,cs int l,cs int r){
        ri int x,y,z,as;
        split(rt,r,x,z),split(x,l-1,x,y);
        as=t[y].sum;
        return rt=merge(merge(x,y),z),as;
    }

    il void ins(int &rt,cs int p,cs int val){
        ri int x,y; split(rt,p,x,y);
        rt=merge(merge(x,add(val)),y);
    }

    il void del(int &rt,cs int val){
        ri int x,y,z;
        split(rt,val,x,z);
        split(x,val-1,x,y);
        rt=merge(x,z);
    }

    #undef ls
    #undef rs
} using namespace fhq_treap;

signed main(){
    ri int n=rd();
    for(ri int i=1,op,l,r,las=0;i<=n;++i){
        rot[i]=rot[rd()],op=rd(),l=rd()^las;
        switch (op){
            case 1:r=rd()^las,ins(rot[i],l,r);break;
            case 2:del(rot[i],l);break;
            case 3:r=rd()^las,rev(rot[i],l,r);break;
            case 4:r=rd()^las,wn(las=ask(rot[i],l,r));break;
        }
    }
    return 0;
}

edit

posted @ 2023-03-23 11:44  雨夜风月  阅读(117)  评论(0编辑  收藏  举报