码迷,mamicode.com
首页 > 其他好文 > 详细

可持久化平衡树

时间:2020-06-29 23:00:33      阅读:61      评论:0      收藏:0      [点我收藏+]

标签:维护   str   upd   algorithm   平衡   data   spl   online   pac   

数据结构 可持久化平衡树

自己开的可持久化的坑,自己含着泪也要补完≡(▔﹏▔)≡

【模板】可持久化平衡树

之前刚刚学过fhq_treap 这个数据结构的强大之处:一在于好写好调,码量友好;二便在于便于可持久化

因为普通treap利用旋转来保持时间复杂度,左旋旋,右旋旋,很难维护父子关系,也很难像主席树那样大规模的利用历史数据。但是非旋treap就有个“形态固定”的优美性质,适合可持久化

直接讲做法:

直接在split做出更改。每一次将一棵树份成两半的时候都新建节点即可。over。就这么点。

new split:

void split(int now,int k,int &x,int &y){
        if(!now) x=y=0;
        else{
            if(val[now]<=k){
                x=++tot;
                copy_node(now,x);
                split(ch[x][1],k,ch[x][1],y);
                updata(x);
            }
            else {
                y=++tot;
                copy_node(now,y);
                split(ch[y][0],k,x,ch[y][0]);
                updata(y);
            }
            updata(now);
        }
    }

完整代码:

#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;
#define FT fhq_treap::

namespace fhq_treap{
    const int MAX=5e7+5;
    int tot,x,y,z;
    int root[MAX],ch[MAX][2],val[MAX],rad[MAX],size[MAX];

    void updata(int k){
        size[k]=1+size[ch[k][0]]+size[ch[k][1]];
    }

    int newnode(int k){
        tot++;
        val[tot]=k;
        rad[tot]=rand();
        size[tot]=1;
        return tot;
    }

    void copy_node(int a,int b){
        val[b]=val[a];
        size[b]=size[a];
        rad[b]=rad[a];
        ch[b][0]=ch[a][0];
        ch[b][1]=ch[a][1];
    }

    void copy(int a,int b){
        root[b]=++tot;
        copy_node(root[a],root[b]);
    }

    void split(int now,int k,int &x,int &y){
        if(!now) x=y=0;
        else{
            if(val[now]<=k){
                x=++tot;
                copy_node(now,x);
                split(ch[x][1],k,ch[x][1],y);
                updata(x);
            }
            else {
                y=++tot;
                copy_node(now,y);
                split(ch[y][0],k,x,ch[y][0]);
                updata(y);
            }
            updata(now);
        }
    }

    int merge(int a,int b){
        if(!a||!b) return a|b;
        else{
            if(rad[a]<rad[b]){
                ch[a][1]=merge(ch[a][1],b);
                updata(a);
                return a;
            }
            else{
                ch[b][0]=merge(a,ch[b][0]);
                updata(b);
                return b;
            }
        }
    }

    void insert(int ver,int k){
        split(root[ver],k,x,z);
        x=merge(x,newnode(k)); root[ver]=merge(x,z);
    }

    void delate(int ver,int k){
        split(root[ver],k-1,x,y);
        split(y,k,y,z);
        y=merge(ch[y][0],ch[y][1]);
        x=merge(x,y); root[ver]=merge(x,z);		
    }

    int rak(int ver,int k){
        split(root[ver],k-1,x,y);
        int ans=size[x]+1;
        root[ver]=merge(x,y);
        return ans;
    }

    int kth(int p,int k){
        int now=p;
        while(now){
            int t=size[ch[now][0]]+1;
            if(t==k) return now;
            else if(k<=t) now=ch[now][0];
            else {k-=t; now=ch[now][1];}
        }
    }

    int pre(int ver,int k){
        split(root[ver],k-1,x,y);
        int ans=val[kth(x,size[x])];
        root[ver]=merge(x,y);
        return ans;
    }

    int suf(int ver,int k){
        split(root[ver],k,x,y);
        int ans=val[kth(y,1)];
        root[ver]=merge(x,y);
        return ans;
    }

    bool exist(int ver,int k){
        split(root[ver],k-1,x,y);
        split(y,k,y,z);
        bool ans=size[y];
        x=merge(x,y); root[ver]=merge(x,z);
        return ans;
    }
}

int n;

int main(){
    #ifndef ONLINE_JUDGE
    freopen("test.in","r",stdin);
    #endif

    FT insert(0,-2147483647);
    FT insert(0,2147483647);

    scanf("%d",&n);
    for(int i=1;i<=n;++i){
        int v,opt,x; scanf("%d%d%d",&v,&opt,&x);
        FT copy(v,i);
        switch(opt){
            case 1:
            FT insert(i,x);
            break;

            case 2:
            FT delate(i,x);
            break;

            case 3:
            printf("%d\n",FT rak(i,x)-1);
            break;

            case 4:
            printf("%d\n",FT val[FT kth(FT root[i],x+1)]);
            break;

            case 5:
            printf("%d\n",FT pre(i,x));
            break;

            case 6:
            printf("%d\n",FT suf(i,x));
            break;
        }
    }

    return 0;
}

可持久化平衡树

标签:维护   str   upd   algorithm   平衡   data   spl   online   pac   

原文地址:https://www.cnblogs.com/ticmis/p/13210593.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!