范浩强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——可持久化的主要内容,如果未能解决你的问题,请参考以下文章