zoukankan      html  css  js  c++  java
  • 范浩强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好理解而且更好写,注意可持久化即可。

    ——by VANE

      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
    ",getkth(i,val));break;
    137             case 4:printf("%d
    ",getval(root[i],val));break;
    138             case 5:printf("%d
    ",getpre(i,val));break;
    139             case 6:printf("%d
    ",getnext(i,val));break;
    140         }
    141     }
    142 }
    生命中真正重要的不是你遭遇了什么,而是你记住了哪些事,又是如何铭记的。
  • 相关阅读:
    JavaScript的运动框架学习总结
    Canvas设置width与height 的问题!
    JavaScript 学习—— js获取行间样式和非行间样式
    Css 学习——left与offsetLeft的区别
    BaseServlet
    Java集合 Json集合之间的转换
    Java对象 json之间的转换(json-lib)
    mybatis hellworld
    XStream的例子
    c语言之“/”和“%”运算符
  • 原文地址:https://www.cnblogs.com/nbwzyzngyl/p/7977369.html
Copyright © 2011-2022 走看看