zoukankan      html  css  js  c++  java
  • 非旋Treap

    最近看到有一种不用旋转的treap,好像还可以持久化,于是就学了一下。

    如果你还不会Treap的话,那你可以点击这里,对旋转Treap有个大致了解,这里就不赘述Treap的性质了。

    treap就是tree+heap。它的每个节点的权值data满足排序二叉树的性质,随机权值key满足堆的性质。由于key是随机的所以它大致是平衡的。
    不基于旋转的treap有两个基本操作:

    merge(a,b):返回一个treap,包含a,b两个treap中的所有节点,但要保证b中所有节点权值都大于等于a。

    split(a,n)返回两个treap l,r。其中l中包含treap a中的前n个节点,r中包含treap a中的剩余节点。

    这两个操作的实现都很简单(这里我们维护小根堆的性质):

    merge(a,b):若a的key< b的key则将a的右儿子变为merge(a的右儿子,b)。
    否则将b的左儿子变为merge(a,b的左儿子)。

    split(a,n):若a左子树的size(记为m)=n则返回a的左子树,a和a的右子树。若m=n-1则返回a的左子树和a,a的右子树。否则若m>n则设{l,r}为split(a的左子树,n)将a的左子树设为r,返回l,a。若m< n-1则设{l,r}为split(a的右子树,n-m-1)将a的右儿子设为l,返回a,r。

    有了这两操作我们就可以实现插入和删除了。

    插入x:找到x所在位置,将其split开,在合并l,x与x,r。

    删除x:找到x的位置,将x与其前后位置都split开,在合并另外两部份。
    其余操作和不同平衡树一样。


    【代码实现】

      1 #include<cstdio>
      2 #include<algorithm>
      3 #define maxn 100010
      4 #define mp make_pair
      5 using namespace std;
      6 typedef pair<int,int> pp;
      7 struct node{
      8     int son[2],val,rd,size;
      9 }t[maxn];
     10 int op,n,root,cnt; 
     11 const int INF=1e9+7;
     12 void updata(int v){t[v].size=t[t[v].son[0]].size+t[t[v].son[1]].size+1;}
     13 pp split(int v,int k)
     14 {
     15     if(k==0)return mp(0,v);
     16     int ls=t[v].son[0],rs=t[v].son[1];
     17     if(t[ls].size==k) {t[v].son[0]=0,updata(v);return mp(ls,v);}
     18     if(t[ls].size+1==k) {t[v].son[1]=0,updata(v);return mp(v,rs);}
     19     if(t[ls].size>k)
     20     {
     21         pp tmp=split(ls,k);
     22         t[v].son[0]=tmp.second,updata(v);
     23         return mp(tmp.first,v);
     24     }
     25     pp tmp=split(rs,k-t[ls].size-1);
     26     t[v].son[1]=tmp.first,updata(v);
     27     return mp(v,tmp.second);
     28 }
     29 int merge(int x,int y)
     30 {
     31     if(!x||!y)return x+y;
     32     if(t[x].rd<t[y].rd) {t[x].son[1]=merge(t[x].son[1],y),updata(x);return x;}
     33     else {t[y].son[0]=merge(x,t[y].son[0]),updata(y);return y;}
     34 }
     35 int rank(int v,int k)
     36 {
     37     int ans=0,tmp=INF;
     38     while(v)
     39     {
     40         if(k==t[v].val)tmp=min(tmp,ans+t[t[v].son[0]].size+1);
     41         if(k>t[v].val)ans+=t[t[v].son[0]].size+1,v=t[v].son[1];
     42         else v=t[v].son[0];
     43     }
     44     return tmp==INF?ans:tmp;
     45 }
     46 int find(int v,int k)
     47 {
     48     while(1)
     49     {
     50         if(t[t[v].son[0]].size+1==k)return t[v].val;
     51         if(t[t[v].son[0]].size>=k)v=t[v].son[0];
     52         else k=k-t[t[v].son[0]].size-1,v=t[v].son[1];
     53     }
     54 }
     55 int pre(int v,int k)
     56 {
     57     int ans=-INF;
     58     while(v)
     59     {
     60         if(t[v].val<k)ans=max(ans,t[v].val),v=t[v].son[1];
     61         else v=t[v].son[0];
     62     }
     63     return ans;
     64 }
     65 int next(int v,int k)
     66 {
     67     int ans=INF;
     68     while(v)
     69     {
     70         if(t[v].val>k)ans=min(ans,t[v].val),v=t[v].son[0];
     71         else v=t[v].son[1];
     72     }
     73     return ans;
     74 }
     75 void insert(int v)
     76 {
     77     int k=rank(root,v);
     78     pp tmp=split(root,k);
     79     t[++cnt].val=v;
     80     t[cnt].rd=rand();
     81     t[cnt].size=1;
     82     root=merge(tmp.first,cnt);
     83     root=merge(root,tmp.second);
     84 }
     85 void del(int v)
     86 {
     87     int k=rank(root,v);
     88     pp tmp1=split(root,k);
     89     pp tmp2=split(tmp1.first,k-1);
     90     root=merge(tmp2.first,tmp1.second);
     91 }
     92 int main()
     93 {
     94     int x;
     95     scanf("%d",&n);
     96     for(int i=1;i<=n;i++)
     97     {
     98         scanf("%d%d",&op,&x);
     99         if(op==1)insert(x);
    100         else if(op==2)del(x);
    101         else if(op==3)printf("%d
    ",rank(root,x));
    102         else if(op==4)printf("%d
    ",find(root,x));
    103         else if(op==5)printf("%d
    ",pre(root,x));
    104         else printf("%d
    ",next(root,x));
    105     }
    106     return 0;
    107 }
  • 相关阅读:
    QPS计算
    Burp学院-信息泄露
    Burp学院-OS命令注入
    Burp学院-SQL注入
    时间格式转换 日期转换
    K8s 1.20x版本nfs动态存储报错 persistentvolume-controller waiting for a volume to be created, either by external provisioner "qgg-nfs-storage" or manually created by system administrator
    K8Snode的自定义状态信息
    kubernetes之node资源紧缺时pod驱逐机制
    K8Snode最大pod数量
    阿里云域名白名单访问限制
  • 原文地址:https://www.cnblogs.com/genius777/p/9368896.html
Copyright © 2011-2022 走看看