数据结构:可持久化平衡树

首先吐槽一下,我刚开始找了一篇看起来很不错的模板代码,然后学习了一遍,然后直接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 }
原文地址:https://www.cnblogs.com/aininot260/p/9519563.html