范浩强treap——可持久化
2017-12-04 15:44
141 查看
当平衡树需要可持久化的时候,意味着我们需要访问以前的某个时间点的平衡树,就要保持以前的树形态不变,新建一个时间戳,构建一棵新的树。
如果用以前的旋转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好理解而且更好写,注意可持久化即可。
——by VANE
#include<bits/stdc++.h> using namespace std; const int N=500005; struct node { int ch[2]; int fix,key,sz; }t[N*50]; int root ,cnt=1; int copynode(int x) { cnt++; t[cnt]=t[x]; return cnt; } void update(int cur) { if(cur) t[cur].sz=t[t[cur].ch[0]].sz+t[t[cur].ch[1]].sz+1; } int newnode(int val) { cnt++; t[cnt].ch[0]=t[cnt].ch[1]=0; t[cnt].key=val; t[cnt].sz=1; t[cnt].fix=rand(); return cnt; } void split(int now,int k,int &x,int &y) { if(!now) x=y=0; else { if(t[now].key<=k) { x=copynode(now); split(t[x].ch[1],k,t[x].ch[1],y); } else { y=copynode(now); split(t[y].ch[0],k,x,t[y].ch[0]); } update(x); update(y); } } int merge(int x,int y) { if(!x||!y) return x+y; if(t[x].fix<t[y].fix) { int r=copynode(x); t[r].ch[1]=merge(t[r].ch[1],y); update(r); return r; } else { int r=copynode(y); t[r].ch[0]=merge(x,t[r].ch[0]); update(r); return r; } } void insert(int bb,int val) { int x,y,z; x=y=z=0; split(root[bb],val,x,y); z=newnode(val); root[bb]=merge(merge(x,z),y); } void Delete(int bb,int val) { int x,y,z; split(root[bb],val,x,z); split(x,val-1,x,y); y=merge(t[y].ch[0],t[y].ch[1]); root[bb]=merge(merge(x,y),z); } int getpos(int now,int k) { while(1) { if(k<=t[t[now].ch[0]].sz) now=t[now].ch[0]; else if(k==t[t[now].ch[0]].sz+1) return now; else k-=t[t[now].ch[0]].sz+1,now=t[now].ch[1]; } } int getkth(int bb,int val) { int x,y; int ret; split(root[bb],val-1,x,y); ret=t[x].sz+1; return ret; } int getval(int now,int k) { int x; x=getpos(now,k); return t[x].key; } int getpre(int bb,int val) { int x,y; int k,ret; split(root[bb],val-1,x,y); if(x) k=t[x].sz; else return -2147483647; ret=getval(x,k); return ret; } int getnext(int bb,int val) { int x,y; split(root[bb],val,x,y); if(!y) return 2147483647; int ret=getval(y,1); return ret; } int main() { int n,bb,cmd,val; scanf("%d",&n); for(int i=1;i<=n;++i) { scanf("%d%d%d",&bb,&cmd,&val); root[i]=root[bb]; switch(cmd) { case 1:insert(i,val);break; case 2:Delete(i,val);break; case 3:printf("%d\n",getkth(i,val));break; case 4:printf("%d\n",getval(root[i],val));break; case 5:printf("%d\n",getpre(i,val));break; case 6:printf("%d\n",getnext(i,val));break; } } }
相关文章推荐
- 可持久化Treap
- 好久不见的博客咯!——没有可持久化的可持久化treap
- 非旋转/可持久化treap(转自Sengxian's Blog)
- UVA 12538 Version Controlled IDE 可持久化treap
- UVA12538 Version Controlled IDE (可持久化Treap)
- 平衡树与可持久化treap
- 可持久化treap学习笔记
- 可持久化Treap学习小结
- 非旋转Treap及可持久化[Merge,Split]
- 可持久化Treap——SPOJ ADALIST
- UVALive 6145 Version Controlled IDE(可持久化treap、rope)
- 可持久化Treap
- 可持久化Treap(fhq Treap,非旋转式Treap)学习(未完待续)
- BZOJ 1208 (可持久化Treap,合并与分裂操作)
- UVA 12538 Version Controlled IDE(可持久化treap)
- 非旋转式treap及可持久化
- 可持久化treap
- 可持久化(非旋转式)treap 学习记录
- POJ 3580 SuperMemo Splay/可持久化Treap 维护区间
- BZOJ 3595: [Scoi2014]方伯伯的Oj SBT+可持久化Treap