Treap,也叫做树堆,是指有一个随机附加域满足堆的性质的二叉搜索树。

如果一棵二叉搜索树插入节点的顺序是随机的,那我们得到的二叉搜索树在大多数情况下是平衡的,期望高度是log(n).

但有些情况下我们并不能得知所有待插入节点,打乱以后再插入,这时我们需要给二叉搜索树加上一个随机附加域,并使这个随机附加域(优先级)满足堆的性质,以此来实现“乱序插入”的想法,使二叉搜索树保持平衡。

Treap可以满足的序列操作:

1,插入一个数x

2,删除一个数x

3,查询x的排名

4,查询排名为x的数

5,查询x的前驱

6,查询x的后继

Treap的基本操作

1,newnode新建节点

2,split分裂 把Treap按照权值分割为两部分

3,merge合并 把Treap的两部分进行合并

4,insert插入 把Treap按照插入的权值Val分裂为两部分,然后merge左边和新点,再merge新的左边和右边

5,delete删除 把Treap分裂两次,中间那部分不管它,把两边merge一下

  1. #include<cstdio>
  2. #include<algorithm>
  3. #define ls (a[u].l)
  4. #define rs (a[u].r)
  5. using namespace std;
  6. const int maxn=;
  7. int n,k,x,y,z,v,tot,root;
  8. struct treap{int l,r,v,rnd,size;}a[maxn];
  9. inline void read(int &k){
  10. k=; int f=; char c=getchar();
  11. while(c<''||c>'')c=='-'&&(f=-),c=getchar();
  12. while(''<=c&&c<='')k=k*+c-'',c=getchar();
  13. k*=f;
  14. }
  15. void newnode(int v){a[++tot]=(treap){,,v,rand()+,};}
  16. void update(int u){a[u].size=a[ls].size+a[rs].size+;}
  17. void split(int u,int k,int &x,int &y){
  18. if(!k){x=; y=u; return;}
  19. if(a[u].size==k){x=u; y=; return;}
  20. if(a[ls].size>=k) split(ls,k,x,ls),y=u;
  21. else split(rs,k-a[ls].size-,rs,y),x=u;
  22. update(u);
  23. }
  24. int merge(int x,int y){
  25. if(!(x*y)) return x+y;
  26. if(a[x].rnd>a[y].rnd){
  27. a[y].l=merge(x,a[y].l); update(y); return y;
  28. }
  29. else{
  30. a[x].r=merge(a[x].r,y); update(x); return x;
  31. }
  32. }
  33. int qrank(int u,int val){
  34. if(!u) return ;
  35. if(a[u].v>=val) return qrank(ls,val);
  36. return qrank(rs,val)+a[ls].size+;
  37. }
  38. int qval(int u,int k){
  39. if(a[ls].size+==k) return a[u].v;
  40. return a[ls].size>=k?qval(ls,k):qval(rs,k-a[ls].size-);
  41. }
  42. int main(){
  43. srand(); root=tot=; a[root].v=2e9; a[root].size=;
  44. read(n);
  45. while(n--){
  46. read(k); read(v);
  47. if(k==){//插入
  48. split(root,qrank(root,v),x,y);
  49. newnode(v); root=merge(merge(x,tot),y);
  50. }
  51. if(k==){//删除
  52. split(root,qrank(root,v),x,y);
  53. split(y,,z,y); root=merge(x,y);
  54. }
  55. if(k==) printf("%d\n",qrank(root,v)+);//查询x的排名
  56. if(k==) printf("%d\n",qval(root,v));//查询排名为x的数
  57. if(k==) printf("%d\n",qval(root,qrank(root,v)));//查询x的前驱
  58. if(k==) printf("%d\n",qval(root,qrank(root,v+)+));//查询x的后继
  59. }
  60. return ;
  61. }
  1. #include<cstdio>
  2. #include<algorithm>
  3. #define ls (a[u].l)
  4. #define rs (a[u].r)
  5. using namespace std;
  6. const int maxn=;
  7. int n,k,x,y,z,v,tot,root;
  8. struct treap{int l,r,v,rnd,size;}a[maxn];
  9. inline int read(){
  10. int k=,f=; char c=getchar();
  11. while(c<''||c>'')c=='-'&&(f=-),c=getchar();
  12. while(''<=c&&c<='')k=k*+c-'',c=getchar();
  13. return k*f;
  14. }
  15. void newnode(int val){a[++tot]=(treap){,,val,rand()+,};}
  16. void update(int u){a[u].size=a[ls].size+a[rs].size+;}
  17. void split(int u,int k,int &x,int &y){
  18. if(!k){x=; y=u; return;}
  19. if(a[u].size==k){x=u; y=; return;}
  20. if(a[ls].size>=k) split(ls,k,x,ls),y=u;
  21. else split(rs,k-a[ls].size-,rs,y),x=u;
  22. update(u);
  23. }
  24. int merge(int x,int y){
  25. if(!x||!y) return x+y;
  26. if(a[x].rnd<a[y].rnd){a[x].r=merge(a[x].r,y); update(x); return x;}
  27. else{a[y].l=merge(x,a[y].l); update(y); return y;}
  28. }
  29. int qrank(int u,int val){
  30. if(!u) return ;
  31. return a[u].v>=val?qrank(ls,val):qrank(rs,val)+a[ls].size+;
  32. }
  33. int qval(int u,int k){
  34. if(a[ls].size+==k) return a[u].v;
  35. return a[ls].size>=k?qval(ls,k):qval(rs,k-a[ls].size-);
  36. }
  37. int main(){
  38. srand(); a[root=tot=]=(treap){,,2e9,,};
  39. n=read();
  40. while(n--){
  41. k=read(); v=read();
  42. if(k==){
  43. split(root,qrank(root,v),x,y);
  44. newnode(v); root=merge(merge(x,tot),y);
  45. }
  46. if(k==){
  47. split(root,qrank(root,v),x,y); split(y,,z,y);
  48. root=merge(x,y);
  49. }
  50. if(k==) printf("%d\n",qrank(root,v)+);
  51. if(k==) printf("%d\n",qval(root,v));
  52. if(k==) printf("%d\n",qval(root,qrank(root,v)));
  53. if(k==) printf("%d\n",qval(root,qrank(root,v+)+));
  54. }
  55. return ;
  56. }

洛谷3369

【模板】非旋转Treap的更多相关文章

  1. BZOJ5063旅游——非旋转treap

    题目描述 小奇成功打开了大科学家的电脑. 大科学家打算前往n处景点旅游,他用一个序列来维护它们之间的顺序.初 始时,序列为1,2,...,n. 接着,大科学家进行m次操作来打乱顺序.每次操作有6步: ...

  2. BZOJ1251序列终结者——非旋转treap

    题目描述 网上有许多题,就是给定一个序列,要你支持几种操作:A.B.C.D.一看另一道题,又是一个序列 要支持几种操作:D.C.B.A.尤其是我们这里的某人,出模拟试题,居然还出了一道这样的,真是没技 ...

  3. 平衡树及笛卡尔树讲解(旋转treap,非旋转treap,splay,替罪羊树及可持久化)

    在刷了许多道平衡树的题之后,对平衡树有了较为深入的理解,在这里和大家分享一下,希望对大家学习平衡树能有帮助. 平衡树有好多种,比如treap,splay,红黑树,STL中的set.在这里只介绍几种常用 ...

  4. 旋转/非旋转treap的简单操作

    treap(树堆) 是在二叉搜索树的基础上,通过维护随机附加域,使其满足堆性质,从而使树相对平衡的二叉树: 为什么可以这样呢? 因为在维护堆的时候可以同时保证搜索树的性质: (比如当一棵树的一个域满足 ...

  5. 非旋转 treap

    其实之前学过一次非旋转 treap,但是全忘光了,今天复习一下. 洛谷 P3369 [模板]普通平衡树 code: #include <bits/stdc++.h> #define N 1 ...

  6. [bzoj3173]最长上升子序列_非旋转Treap

    最长上升子序列 bzoj-3173 题目大意:有1-n,n个数,第i次操作是将i加入到原有序列中制定的位置,后查询当前序列中最长上升子序列长度. 注释:1<=n<=10,000,开始序列为 ...

  7. 关于非旋转treap的学习

    非旋转treap的操作基于split和merge操作,其余操作和普通平衡树一样,复杂度保证方式与旋转treap差不多,都是基于一个随机的参数,这样构出的树树高为\(logn\) split 作用:将原 ...

  8. [Codeforces702F]T-Shirts——非旋转treap+贪心

    题目链接: Codeforces702F 题目大意:有$n$种T恤,每种有一个价格$c_{i}$和品质$q_{i}$且每种数量无限.现在有$m$个人,第$i$个人有$v_{i}$元,每人每次会买他能买 ...

  9. BZOJ3223文艺平衡树——非旋转treap

    此为平衡树系列第二道:文艺平衡树您需要写一种数据结构,来维护一个有序数列,其中需要提供以下操作: 翻转一个区间,例如原有序序列是5 4 3 2 1,翻转区间是[2,4]的话,结果是5 2 3 4 1 ...

  10. BZOJ3224普通平衡树——非旋转treap

    题目: 此为平衡树系列第一道:普通平衡树您需要写一种数据结构,来维护一些数,其中需要提供以下操作:1. 插入x数2. 删除x数(若有多个相同的数,因只删除一个)3. 查询x数的排名(若有多个相同的数, ...

随机推荐

  1. Linux gadget驱动分析2------设备识别过程

    设备连上主机之后,设备驱动做了的事. 设备连上host的port之后,主机端会有一套策略发送请求获取device的一系列描述符.进行枚举过程.找到适合该device的驱动. 这样就可以与device进 ...

  2. Unix域套接字(Unix Domain Socket)介绍【转】

    本文转载自:http://blog.csdn.net/roland_sun/article/details/50266565 版权声明:本文为博主原创文章,未经博主允许不得转载. 在Linux系统中, ...

  3. 第四章、TIny4412 U-BOOT移植四 配置时钟频率源码分析【转】

    本文转载自:http://blog.csdn.net/eshing/article/details/37542459 版权声明:本文为博主原创文章,未经博主允许不得转载.   目录(?)[+]   上 ...

  4. P3959 宝藏 状压dp

    之前写了一份此题关于模拟退火的方法,现在来补充一下状压dp的方法. 其实直接在dfs中状压比较好想,而且实现也很简单,但是网上有人说这种方法是错的...并不知道哪错了,但是就不写了,找了一个正解. 正 ...

  5. 8.3 TCPIP协议族

    接下来我们要学习的内容是TCP/IP协议族.TCP/IP协议族在网络系统中是非常重要的.这一个协议族当中牵涉到许许多多的我们平常所用到的协议.TCP/IP呢它也有分层模型.然后我们讲到的就是三方面的内 ...

  6. Java开源JSP标签库

    01displytag 与Struts结合使用最出名的一个tag主要是显示表格数据很漂亮.完善. 02cewolf tag 用来在web上显示复杂图形报表的一个jsp tag. 03Loading T ...

  7. Linux扩展正则表达式

    1. 扩展正则表达式 1.1 +(加号) + 表示前一个字符出现1次或1次以上 1.1.1 理解+ 要求:取出文件内容连续出现的小写字母 [root@oldboyedu50-lnb /oldboy]# ...

  8. 页面渐进式消失【JS代码】

    // 设定时间,页面慢慢变透明,直到消失 var opacityInterval = setInterval(function () { // 普通时间转为格林威治时间 var targetDate ...

  9. JavaScript--String 字符串对象属性

    访问字符串对象的属性length: stringObject.length; 返回该字符串的长度. var mystr="Hello World!"; var myl=mystr. ...

  10. Educational Codeforces Round 24 题解

    A: 考你会不会除法 //By SiriusRen #include <bits/stdc++.h> using namespace std; #define int long long ...