首先吐槽一下,我刚开始找了一篇看起来很不错的模板代码,然后学习了一遍,然后直接WA
我发现博主的维护rnd的那里出毛病了,我改了之后最后一个点WA
然后发现,它没有copy结点,也就是没有可持久化,只是一颗无旋Treap而已。。
不说了,感谢引导我走向正确的作者:http://www.cnblogs.com/nbwzyzngyl/p/7977369.html
这是一种非常好写的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<cstdio> 2 #include<cstdlib> 3 int cnt; 4 int rt[500005]; 5 struct Node 6 { 7 int l,r,size,rnd,v; 8 }t[500005*50]; 9 void update(int k) 10 { 11 t[k].size=t[t[k].l].size+t[t[k].r].size+1; 12 } 13 void newnode(int &k,int x) 14 { 15 k=++cnt; 16 t[k].v=x;t[k].size=1;t[k].rnd=rand(); 17 } 18 int merge(int a,int b) 19 { 20 if(a==0||b==0)return a+b; 21 if(t[a].rnd>t[b].rnd) 22 { 23 int p=++cnt;t[p]=t[a]; 24 t[p].r=merge(t[p].r,b); 25 update(p);return p; 26 } 27 else 28 { 29 int p=++cnt;t[p]=t[b]; 30 t[p].l=merge(a,t[p].l); 31 update(p);return p; 32 } 33 } 34 void split(int now,int k,int &x,int &y) 35 { 36 if(now==0) x=y=0; 37 else 38 { 39 if(t[now].v<=k) 40 { 41 x=++cnt;t[x]=t[now]; 42 split(t[x].r,k,t[x].r,y); 43 update(x); 44 } 45 else 46 { 47 y=++cnt;t[y]=t[now]; 48 split(t[y].l,k,x,t[y].l); 49 update(y); 50 } 51 } 52 } 53 void Delete(int &root,int w) 54 { 55 int x=0,y=0,z=0; 56 split(root,w,x,z); 57 split(x,w-1,x,y); 58 y=merge(t[y].l,t[y].r); 59 root=merge(merge(x,y),z); 60 } 61 void Insert(int &root,int w) 62 { 63 int x=0,y=0,z=0; 64 split(root,w,x,y); 65 newnode(z,w); 66 root=merge(merge(x,z),y); 67 } 68 int getval(int k,int w) 69 { 70 if(w==t[t[k].l].size+1)return t[k].v; 71 else if(w<=t[t[k].l].size)return getval(t[k].l,w); 72 else return getval(t[k].r,w-t[t[k].l].size-1); 73 } 74 int getkth(int &root,int w) 75 { 76 int x,y; 77 split(root,w-1,x,y); 78 int ans=t[x].size+1; 79 root=merge(x,y); 80 return ans; 81 } 82 int getpre(int &root,int w) 83 { 84 int x,y,k,ans; 85 split(root,w-1,x,y); 86 if(!x)return -2147483647; 87 k=t[x].size; 88 ans=getval(x,k); 89 root=merge(x,y); 90 return ans; 91 } 92 int getnex(int &root,int w) 93 { 94 int x,y,ans; 95 split(root,w,x,y); 96 if(!y)return 2147483647; 97 else ans=getval(y,1); 98 root=merge(x,y); 99 return ans; 100 } 101 int main() 102 { 103 int n,f,w,tim; 104 scanf("%d",&n); 105 for(int i=1;i<=n;++i) 106 { 107 scanf("%d%d%d",&tim,&f,&w); 108 rt[i]=rt[tim]; 109 if(f==1) Insert(rt[i],w); 110 else if(f==2) Delete(rt[i],w); 111 else if(f==3) printf("%d ",getkth(rt[i],w)); 112 else if(f==4) printf("%d ",getval(rt[i],w)); 113 else if(f==5) printf("%d ",getpre(rt[i],w)); 114 else printf("%d ",getnex(rt[i],w)); 115 } 116 return 0; 117 }