范浩强treap——可持久化

Posted 大奕哥&VANE

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了范浩强treap——可持久化相关的知识,希望对你有一定的参考价值。

当平衡树需要可持久化的时候,意味着我们需要访问以前的某个时间点的平衡树,就要保持以前的树形态不变,新建一个时间戳,构建一棵新的树。

如果用以前的旋转treap可能就不方便做到(又要打时间戳,又要新建节点,又要旋转),而且涉及到旋转,空间可能会承受不住,我们需要用到一种新的平衡树——fhq treap

 

这是一种非常好写的treap 核心操作有两个,一个是split一个是merge。

split(node,k,x,y) 意思是把以node为跟的子树分成两部分,一部分小于等于k(根为x),一部分大于k(根为y)。在可持久化的时候要保证以前的树的形态不变,就要每一次copy一个节点过来。

而我们每一次递归只会访问一个节点的左右子树中的一个节点,又因为treap的均摊深度为log,所以总体的空间为nlogn,是非常高效的。

说完split接下来是merge

merge函数,是有返回值的,merge(x,y) 是把以x为根的子树和以y为根的子树合并起来,返回这棵新的树的根,递归的实现,非常好懂。

接下来的所有操作都是基于以上两个核心的操作,非常好理解,比旋转的treap好理解而且更好写,注意可持久化即可。

 

  1 #include<bits/stdc++.h>
  2 using namespace std;
  3 const int N=500005;
  4 struct node
  5 {
  6     int ch[2];
  7     int fix,key,sz;
  8 }t[N*50];
  9 int root[N],cnt=1;
 10 int copynode(int x)
 11 {
 12     cnt++;
 13     t[cnt]=t[x];
 14     return cnt;
 15 }
 16 void update(int cur)
 17 {
 18     if(cur)
 19     t[cur].sz=t[t[cur].ch[0]].sz+t[t[cur].ch[1]].sz+1;
 20 }
 21 int newnode(int val)
 22 {
 23     cnt++;
 24     t[cnt].ch[0]=t[cnt].ch[1]=0;
 25     t[cnt].key=val;
 26     t[cnt].sz=1;
 27     t[cnt].fix=rand();
 28     return cnt;
 29 }
 30 void split(int now,int k,int &x,int &y)
 31 {
 32     if(!now) x=y=0;
 33     else
 34     {
 35         if(t[now].key<=k)
 36         {
 37             x=copynode(now);
 38             split(t[x].ch[1],k,t[x].ch[1],y);
 39         }
 40         else
 41         {
 42             y=copynode(now);
 43             split(t[y].ch[0],k,x,t[y].ch[0]);
 44         }
 45         update(x);
 46         update(y);
 47     }
 48 }
 49 int merge(int x,int y)
 50 {
 51     if(!x||!y) return x+y;
 52     if(t[x].fix<t[y].fix)
 53     {
 54         int r=copynode(x);
 55         t[r].ch[1]=merge(t[r].ch[1],y);
 56         update(r);
 57         return r;
 58     }
 59     else
 60     {
 61         int r=copynode(y);
 62         t[r].ch[0]=merge(x,t[r].ch[0]);
 63         update(r);
 64         return r;
 65     }
 66 }
 67 void insert(int bb,int val)
 68 {
 69     int x,y,z;
 70     x=y=z=0;
 71     split(root[bb],val,x,y);
 72     z=newnode(val);
 73     root[bb]=merge(merge(x,z),y);
 74 }
 75 void Delete(int bb,int val)
 76 {
 77     int x,y,z;
 78     split(root[bb],val,x,z);
 79     split(x,val-1,x,y);
 80     y=merge(t[y].ch[0],t[y].ch[1]);
 81     root[bb]=merge(merge(x,y),z);
 82 }
 83 int getpos(int now,int k)
 84 {
 85     while(1)
 86     {
 87         if(k<=t[t[now].ch[0]].sz) now=t[now].ch[0];
 88         else if(k==t[t[now].ch[0]].sz+1) return now;
 89         else k-=t[t[now].ch[0]].sz+1,now=t[now].ch[1];
 90     }
 91 }
 92 int getkth(int bb,int val)
 93 {
 94     int x,y;
 95     int ret;
 96     split(root[bb],val-1,x,y);
 97     ret=t[x].sz+1;
 98     return ret;
 99 }
100 int getval(int now,int k)
101 {
102     int x;
103     x=getpos(now,k);
104     return t[x].key;
105 }
106 int getpre(int bb,int val)
107 {
108     int x,y;
109     int k,ret;
110     split(root[bb],val-1,x,y);
111     if(x) k=t[x].sz;
112     else return -2147483647;
113     ret=getval(x,k);
114     return ret;
115 }
116 int getnext(int bb,int val)
117 {
118     int x,y;
119     split(root[bb],val,x,y);
120     if(!y) return 2147483647;
121     int ret=getval(y,1);
122     return ret;
123 }
124 int main()
125 {
126     int n,bb,cmd,val;
127     scanf("%d",&n);
128     for(int i=1;i<=n;++i)
129     {
130         scanf("%d%d%d",&bb,&cmd,&val);
131         root[i]=root[bb];
132         switch(cmd)
133         {
134             case 1:insert(i,val);break;
135             case 2:Delete(i,val);break;
136             case 3:printf("%d\n",getkth(i,val));break;
137             case 4:printf("%d\n",getval(root[i],val));break;
138             case 5:printf("%d\n",getpre(i,val));break;
139             case 6:printf("%d\n",getnext(i,val));break;
140         }
141     }
142 }

 

以上是关于范浩强treap——可持久化的主要内容,如果未能解决你的问题,请参考以下文章

数据结构FHQ Treap详解

LG3369 模板普通平衡树

非旋Treap

可持久化Treap(fhq Treap,非旋转式Treap)学习(未完待续)

uva12538

luoguP5055 模板可持久化文艺平衡树 可持久化非旋转treap