zoukankan      html  css  js  c++  java
  • [Data]FHQ treap

    <范浩强treap>-函数式平衡树

    范好强treap是一种毒瘤treap,它并不用通过旋转来达到平衡,它主要有两种操作:

    merge(x,y):将x的子树和y的子树合并起来;{注意:merge操作中,x子树中的最大值永远会小于等于y子树中的最小值

    所以在merge的过程中只需要考虑随机值,而不需考虑key值}所以merge时要不就x连接在y的左儿子,

    要不就y连接在x的右儿子,这时就需通过随机值来确定哪个为儿子。

     1 int merge(int x,int y){
     2         //printf("merge:%d %d
    ",x,y);
     3     if(!x||!y) return x+y;
     4     else{
     5         if(t[x].fix<t[y].fix){
     6             int r=copynode(x);
     7             t[r].son[1]=merge(t[r].son[1],y);
     8             update(r);
     9             return r;
    10         }
    11         else{
    12             int r=copynode(y);
    13             t[r].son[0]=merge(x,t[r].son[0]);
    14             update(r);
    15             return r;
    16         }
    17     }
    18 }
    merge

    split(k,x,y):将小于等于k值的数分离到以x为根的子树中,另外一部分分离到y;只需判断当前节点与k的关系,

    若小于等于K,则它的左儿子就一定小于k,但右儿子就不一定了;若大于K,则它的右儿子就一定大于k,左儿子就不一定了。

     1 void split(int now,int k,int &x,int &y){
     2     //printf("split:%d %d
    ",x,y);
     3     if(!now) x=y=0;
     4     else{
     5         if(t[now].key<=k){
     6             x=copynode(now);
     7             split(t[x].son[1],k,t[x].son[1],y);
     8         }
     9         else{
    10             y=copynode(now);
    11             split(t[y].son[0],k,x,t[y].son[0]);
    12         }
    13         update(x);
    14         update(y);
    15     }
    16 }
    split

    以下的操作均是通过merge和split实现的:

    《insert》——插入

    设插入的值为k,只需要把当前的树split(k,x,y),k单独一棵树,然后再merge(k,x),最后merge(merge(k,x),y);

    1 void insert(int bb,int val){
    2     int x,y,z;
    3     x=y=z=0;
    4     split(root[bb],val,x,y);
    5     z=newnode(val);
    6     root[bb]=merge(merge(x,z),y);
    7 }
    insert

    《delet》——删除

    只需要先把树分成大于删除值与小于等于删除值两部分z,x,再在x中分离出小于删除值与等于删除值的树x,y,在y子树中,由于我们只要删除一个数,

    所以只需删除y中的根节点,再把y的左右儿子合并起来。

    1 void del(int bb,int val){
    2     int x=0,y=0,z=0;
    3     split(root[bb],val,x,z);
    4     split(x,val-1,x,y);
    5     y=merge(t[y].son[0],t[y].son[1]);
    6     root[bb]=merge(merge(x,y),z);
    7 }
    delet

    求第k值的排名(比它小的数+1)——getkth

    分离出小于k的数存在树x中,然后排名等于x的子树+1。

    1 int getkth(int bb,int val){
    2     int x,y,ret;
    3     split(root[bb],val-1,x,y);
    4     ret=t[x].sz+1;
    5     return ret;
    6 }
    getkth

    求排名为k的数——getval

    用一个while循环即可获得排名为k的值emm 。

     1 int getpos(int now,int k){
     2     while(1){
     3         if(k<=t[t[now].son[0]].sz) now=t[now].son[0];
     4         else if(k==t[t[now].son[0]].sz+1) {return now;}
     5         else{
     6             k-=t[t[now].son[0]].sz+1;
     7             now=t[now].son[1];
     8         }
     9     }
    10 }
    11 int getval(int now,int k){
    12     int x;
    13     x=getpos(now,k);
    14     //printf("pos:%d
    ",x);
    15     return t[x].key;
    16 }
    getval

    求val前驱——getpre

    先split(val-1,x,y),然后转换为求排名为k(sz[x])的数即可。

    1 int getpre(int bb,int val){
    2     int x,y,k,ret;
    3     split(root[bb],val-1,x,y);
    4     if(x) k=t[x].sz;
    5     else return -2147483647;
    6     ret=getval(x,k);
    7     return ret;
    8 }
    getpre

    求val后继——getsuc

    原理与求pre一样吧嗯嗯。

    1 int getsuc(int bb,int val){
    2     int x,y,ret;
    3     split(root[bb],val,x,y);
    4     if(!y) return 2147483647;
    5     ret=getval(y,1);
    6     return ret;
    7 }
    getsuc

    luogu 3835:

                                                                                 
      1 #include<cstdio>
      2 #include<iostream>
      3 #include<algorithm>
      4 #define maxn 500009
      5 using namespace std;
      6 struct node{
      7     int son[2];
      8     int fix,key,sz;
      9 }t[maxn*50];
     10 int root[maxn],cnt=1;
     11 int copynode(int x){
     12     cnt++;
     13     t[cnt]=t[x];
     14     return cnt;
     15 }
     16 void update(int cur){
     17     if(cur)t[cur].sz=t[t[cur].son[0]].sz+t[t[cur].son[1]].sz+1;
     18 }
     19 int newnode(int val){
     20     cnt++;
     21     t[cnt].son[0]=t[cnt].son[1]=0;
     22     t[cnt].key=val;
     23     t[cnt].sz=1;
     24     t[cnt].fix=rand();
     25     return cnt;
     26 }
     27 void split(int now,int k,int &x,int &y){
     28     //printf("split:%d %d
    ",x,y);
     29     if(!now) x=y=0;
     30     else{
     31         if(t[now].key<=k){
     32             x=copynode(now);
     33             split(t[x].son[1],k,t[x].son[1],y);
     34         }
     35         else{
     36             y=copynode(now);
     37             split(t[y].son[0],k,x,t[y].son[0]);
     38         }
     39         update(x);
     40         update(y);
     41     }
     42 }
     43 int merge(int x,int y){
     44         //printf("merge:%d %d
    ",x,y);
     45     if(!x||!y) return x+y;
     46     else{
     47         if(t[x].fix<t[y].fix){
     48             int r=copynode(x);
     49             t[r].son[1]=merge(t[r].son[1],y);
     50             update(r);
     51             return r;
     52         }
     53         else{
     54             int r=copynode(y);
     55             t[r].son[0]=merge(x,t[r].son[0]);
     56             update(r);
     57             return r;
     58         }
     59     }
     60 }
     61 void insert(int bb,int val){
     62     int x,y,z;
     63     x=y=z=0;
     64     split(root[bb],val,x,y);
     65     z=newnode(val);
     66     root[bb]=merge(merge(x,z),y);
     67 }
     68 void del(int bb,int val){
     69     int x=0,y=0,z=0;
     70     split(root[bb],val,x,z);
     71     split(x,val-1,x,y);
     72     y=merge(t[y].son[0],t[y].son[1]);
     73     root[bb]=merge(merge(x,y),z);
     74 }
     75 int getkth(int bb,int val){
     76     int x,y,ret;
     77     split(root[bb],val-1,x,y);
     78     ret=t[x].sz+1;
     79     return ret;
     80 }
     81 int getpos(int now,int k){
     82     while(1){
     83         if(k<=t[t[now].son[0]].sz) now=t[now].son[0];
     84         else if(k==t[t[now].son[0]].sz+1) {return now;}
     85         else{
     86             k-=t[t[now].son[0]].sz+1;
     87             now=t[now].son[1];
     88         }
     89     }
     90 }
     91 int getval(int now,int k){
     92     int x;
     93     x=getpos(now,k);
     94     //printf("pos:%d
    ",x);
     95     return t[x].key;
     96 }
     97 int getpre(int bb,int val){
     98     int x,y,k,ret;
     99     split(root[bb],val-1,x,y);
    100     if(x) k=t[x].sz;
    101     else return -2147483647;
    102     ret=getval(x,k);
    103     return ret;
    104 }
    105 int getsuc(int bb,int val){
    106     int x,y,ret;
    107     split(root[bb],val,x,y);
    108     if(!y) return 2147483647;
    109     ret=getval(y,1);
    110     return ret;
    111 }
    112 int main()
    113 {
    114     int n,bb,opt,val;
    115     scanf("%d",&n);
    116     for(int i=1;i<=n;i++){
    117         scanf("%d%d%d",&bb,&opt,&val);
    118         root[i]=root[bb];
    119         switch(opt){
    120             case 1:insert(i,val);break;
    121             case 2:del(i,val); break;
    122             case 3:printf("%d
    ",getkth(i,val));break;
    123             case 4:printf("%d
    ",getval(root[i],val));break;
    124             case 5:printf("%d
    ",getpre(i,val));break;
    125             case 6:printf("%d
    ",getsuc(i,val));break;
    126         }
    127     }
    128           return 0;  
    129 }        
    FHQ treap
  • 相关阅读:
    input上传mp3格式文件,预览并且获取时间
    jquery 页面input上传图后显示
    将String类型的字符串拼接成以逗号分隔的字符输出
    layui select多选下拉显示 以及回显
    input输入框只能输入数字和英文逗号
    电脑开机右下角有小金锁,并且提示一分钟后重启电脑
    修改tomcat控制台的标题
    VC防止程序被多次运行 互斥体方法
    VC中遍历进程并获取进程信息
    VC中遍历目标进程中的模块
  • 原文地址:https://www.cnblogs.com/Fish-/p/8178731.html
Copyright © 2011-2022 走看看