ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

可持久化平衡树

2022-02-02 08:31:39  阅读:166  来源: 互联网

标签:持久 val rs int ls inline 平衡 size


这里主要讲一下为什么 merge 函数需要新建节点的问题,以免以后忘掉。其他都是在分裂与更新的时候新建节点的问题。

这张图片是我们执行分裂后,\(9,4\) 分别是我们分裂出来的两颗子树。

然后我们考虑对 \(9,4\) 执行合并操作。因为 \(9,10,4\) 使我们新建的节点,所以我们他们的 \(key\) 值是随机的,合并之后的树可能和原树不一样。这种情况下,\(4\) 就有可能成为 \(6\) 的右儿子,这就对其他版本的树产生了干扰,所以我们需要新建节点。

代码:


#include<bits/stdc++.h>
#define dd double
#define ld long double
#define ll long long
#define uint unsigned int
#define ull unsigned long long
#define N 30000010
#define M number
using namespace std;

const int INF=2147483647;

template<typename T> inline void read(T &x) {
    x=0; int f=1;
    char c=getchar();
    for(;!isdigit(c);c=getchar()) if(c == '-') f=-f;
    for(;isdigit(c);c=getchar()) x=x*10+c-'0';
    x*=f;
}

inline int random(int n){return 1ll*rand()*rand()%n+1;}

struct Node{
    int val,size,ls,rs,key;
    inline Node(){}
    inline Node(int val,int size,int ls,int rs,int key) : val(val),size(size),ls(ls),rs(rs),key(key) {}
    inline void Print(){
        printf("%d %d %d %d %d\n",val,size,ls,rs,key);
    }
};

Node p[N];
int tot,root[N],rt;

#define ls(k) p[k].ls
#define rs(k) p[k].rs
struct FHQ_Treap{
    inline int NewNode(int val){
        ++tot;p[tot]=Node(val,1,0,0,random(INF));return tot;
    }
    inline void PushUp(int k){p[k].size=p[ls(k)].size+p[rs(k)].size+1;}
    inline void Split(int k,int val,int &x,int &y){
        if(!k){x=y=0;return;}
        if(p[k].val<=val){x=k;Split(rs(k),val,rs(k),y);}
        else{y=k;Split(ls(k),val,x,ls(y));}PushUp(k);
    }
    inline int Merge(int x,int y){
        if(!x||!y) return x+y;
        if(p[x].key<=p[y].key){ls(y)=Merge(x,ls(y));PushUp(y);return y;}
        else{rs(x)=Merge(rs(x),y);PushUp(x);return x;}
    }
    inline void Split_(int k,int val,int &x,int &y){
        // printf("k=%d\n",k);printf("ls=%d rs=%d\n",ls(k),rs(k));
        if(!k){x=y=0;return;}
        if(p[k].val<=val){++tot;p[tot]=p[k];x=tot;Split_(rs(x),val,rs(x),y);PushUp(x);}
        else{++tot;p[tot]=p[k];y=tot;Split_(ls(y),val,x,ls(y));PushUp(y);}
    }
    inline int Merge_(int x,int y){
        if(!x||!y) return x+y;
        if(p[x].key<=p[y].key){int k=++tot;p[k]=p[y];ls(k)=Merge_(x,ls(k));PushUp(k);return k;}
        else{int k=++tot;p[k]=p[x];rs(k)=Merge_(rs(k),y);PushUp(k);return k;}
    }
    inline void Insert(int last,int val,int id){
        int x,y;Split_(root[last],val,x,y);root[id]=Merge_(Merge_(x,NewNode(val)),y);
    }
    inline void Delete(int last,int val,int id){
        int x,y,z;Split_(root[last],val-1,x,y);
        Split_(y,val,y,z);if(y) y=Merge_(ls(y),rs(y));
        root[id]=Merge_(Merge_(x,y),z);
    }
    inline int GetRank(int last,int val,int id){
        root[id]=root[last];int x,y;Split(root[id],val-1,x,y);int ans=p[x].size+1;
        root[id]=Merge(x,y);return ans;
    }
    inline int GetVal(int last,int rank,int id){
        root[id]=root[last];int k=root[id];
        // printf("root[%d]=%d\n",id,root[id]);
        // printf("ls=%d rs=%d val=%d\n",ls(k),rs(k),p[k].val);
        // printf("%d\n",p[1].val);
        while(k){
            if(p[ls(k)].size+1==rank) return p[k].val;
            else if(p[ls(k)].size+1>rank) k=ls(k);
            else{rank-=p[ls(k)].size+1;k=rs(k);}
        }return INF-3;
    }
    inline int GetNext(int last,int val,int id){
        root[id]=root[last];int x,y;Split(root[id],val,x,y);
        int k=y;while(ls(k)) k=ls(k);int ans;if(!k) ans=INF;else ans=p[k].val;
        root[id]=Merge(x,y);return ans;
    }
    inline int GetPre(int last,int val,int id){
        root[id]=root[last];int x,y;Split(root[id],val-1,x,y);
        int k=x;while(rs(k)) k=rs(k);int ans;if(!k) ans=-INF;else ans=p[k].val;
        root[id]=Merge(x,y);return ans;
    }
}tr;

int n;

int main(){
    // freopen("my.in","r",stdin);
    // freopen("my.out","w",stdout);
    read(n);
    for(int i=1;i<=n;i++){
        int last,op,val;
        read(last);read(op);read(val);
        if(op==1) tr.Insert(last,val,i);
        else if(op==2) tr.Delete(last,val,i);
        else if(op==3) printf("%d\n",tr.GetRank(last,val,i));
        else if(op==4) printf("%d\n",tr.GetVal(last,val,i));
        else if(op==5) printf("%d\n",tr.GetPre(last,val,i));
        else if(op==6) printf("%d\n",tr.GetNext(last,val,i));
    }
    return 0;
}

标签:持久,val,rs,int,ls,inline,平衡,size
来源: https://www.cnblogs.com/TianMeng-hyl/p/15860047.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有