P3369 【模板】普通平衡树(Treap/SBT)
时间:2022-05-10
本文章向大家介绍P3369 【模板】普通平衡树(Treap/SBT),主要内容包括其使用实例、应用技巧、基本知识点总结和需要注意事项,具有一定的参考价值,需要的朋友可以参考一下。
题目描述
您需要写一种数据结构(可参考题目标题),来维护一些数,其中需要提供以下操作:
- 插入x数
- 删除x数(若有多个相同的数,因只删除一个)
- 查询x数的排名(若有多个相同的数,因输出最小的排名)
- 查询排名为x的数
- 求x的前驱(前驱定义为小于x,且最大的数)
- 求x的后继(后继定义为大于x,且最小的数)
输入输出格式
输入格式:
第一行为n,表示操作的个数,下面n行每行有两个数opt和x,opt表示操作的序号(1<=opt<=6)
输出格式:
对于操作3,4,5,6每行输出一个数,表示对应答案
输入输出样例
输入样例#1:
10
1 106465
4 1
1 317721
1 460929
1 644985
1 84185
1 89851
6 81968
1 492737
5 493598
输出样例#1:
106465
84185
492737
说明
时空限制:1000ms,128M
1.n的数据范围:n<=100000
2.每个数的数据范围:[-1e7,1e7]
来源:Tyvj1728 原名:普通平衡树
在此鸣谢
FHQ Treap。。。
这是我迄今为止见过最神奇没有之一的数据结构!。
它可以用简单的两个非旋转操作模拟出BST的所有操作。
unbelievable。
有空要好好写一篇关于这个的博客
1 #include<iostream>
2 #include<cstdio>
3 #include<cstring>
4 #include<cmath>
5 #include<algorithm>
6 #include<cstdlib>
7 #include<ctime>
8 using namespace std;
9 const int MAXN=100001;
10 static void read(int &n)
11 {
12 char c='+';int x=0;bool flag=0;
13 while(c<'0'||c>'9'){c=getchar();if(c=='-')flag=1;}
14 while(c>='0'&&c<='9'){x=(x<<1)+(x<<3)+(c-48);c=getchar();}
15 flag==1?n=-x:n=x;
16 }
17 int ch[MAXN][3];// 0左孩子 1右孩子
18 int val[MAXN];// 每一个点的权值
19 int pri[MAXN];// 随机生成的附件权值
20 int siz[MAXN];// 以i为节点的树的节点数量
21 int sz;// 总结点的数量
22 void update(int x)
23 {
24 siz[x]=1+siz[ch[x][0]]+siz[ch[x][1]];
25 }
26 int new_node(int v)
27 {
28 siz[++sz]=1;// 新开辟一个节点
29 val[sz]=v;
30 pri[sz]=rand();
31 return sz;
32 }
33 int merge(int x,int y)// 合并
34 {
35 if(!x||!y) return x+y;// x和y中必定有一个是0
36 if(pri[x]<pri[y])// 把x加到左边的树上
37 {
38 ch[x][1]=merge(ch[x][1],y);// 不懂的看GIF图
39 update(x);
40 return x;
41 }
42 else
43 {
44 ch[y][0]=merge(x,ch[y][0]);
45 update(y);
46 return y;
47 }
48 }
49 void split(int now,int k,int &x,int &y)
50 {
51 if(!now) x=y=0;// 到达叶子节点
52 else
53 {
54 if(val[now]<=k)// 分离右子树
55 x=now,split(ch[now][1],k,ch[now][1],y);
56 else
57 y=now,split(ch[now][0],k,x,ch[now][0]);
58 update(now);
59 }
60 }
61 int kth(int now,int k)// 查询排名
62 {
63 while(1)
64 {
65 if(k<=siz[ch[now][0]])
66 now=ch[now][0];// 在左子树中,且数量小于左子树的大小,迭代寻找
67 else if(k==siz[ch[now][0]]+1)
68 return now;// 找到了
69 else
70 k-=siz[ch[now][0]]+1,now=ch[now][1];// 去右子树找
71 }
72 }
73 int main()
74 {
75 srand((unsigned)time(NULL));
76 int n;
77 read(n);
78 int root=0,x,y,z;
79 for(int i=1;i<=n;i++)
80 {
81 int how,a;
82 read(how);read(a);
83 if(how==1)// 插入
84 {
85 split(root,a,x,y);
86 root=merge(merge(x,new_node(a)),y);
87 }
88 else if(how==2)//删除x
89 {
90 split(root,a,x,z);
91 split(x,a-1,x,y);
92 y=merge(ch[y][0],ch[y][1]);
93 root=merge(merge(x,y),z);
94 }
95 else if(how==3)//查询x的排名
96 {
97 split(root,a-1,x,y);
98 printf("%dn",siz[x]+1);
99 root=merge(x,y);
100 }
101 else if(how==4)// 查询排名为x的数
102 {
103 printf("%dn",val[kth(root,a)]);
104 }
105 else if(how==5)// 求x的前驱
106 {
107 split(root,a-1,x,y);
108 printf("%dn",val[kth(x,siz[x])]);
109 root=merge(x,y);
110 }
111 else if(how==6)// 求x的后继
112 {
113 split(root,a,x,y);
114 printf("%dn",val[kth(y,1)]);
115 root=merge(x,y);
116 }
117 }
118 return 0;
119 }
- 14.3 NFS配置选项
- 14.2 NFS服务端安装配置
- React Native组件之Button
- JDK容器学习之TreeMap (二) : 使用说明
- 从React和angular看技术路线的分歧
- JDK容器学习之LinkedHashMap (一):底层存储结构分析
- Linux基础(day60)
- 16.5/16.6/16.7 配置Tomcat虚拟主机
- JDK容器学习之LinkedHashMap(二):迭代遍历的实现方式
- React Native 实现基于react-native-tab-navigator库Tab切换封装
- 16.4 配置Tomcat监听80端口
- JDK容器学习之Queue:LinkedBlockingQueue
- Linux基础(day59)
- 16.3 安装Tomcat
- JavaScript 教程
- JavaScript 编辑工具
- JavaScript 与HTML
- JavaScript 与Java
- JavaScript 数据结构
- JavaScript 基本数据类型
- JavaScript 特殊数据类型
- JavaScript 运算符
- JavaScript typeof 运算符
- JavaScript 表达式
- JavaScript 类型转换
- JavaScript 基本语法
- JavaScript 注释
- Javascript 基本处理流程
- Javascript 选择结构
- Javascript if 语句
- Javascript if 语句的嵌套
- Javascript switch 语句
- Javascript 循环结构
- Javascript 循环结构实例
- Javascript 跳转语句
- Javascript 控制语句总结
- Javascript 函数介绍
- Javascript 函数的定义
- Javascript 函数调用
- Javascript 几种特殊的函数
- JavaScript 内置函数简介
- Javascript eval() 函数
- Javascript isFinite() 函数
- Javascript isNaN() 函数
- parseInt() 与 parseFloat()
- escape() 与 unescape()
- Javascript 字符串介绍
- Javascript length属性
- javascript 字符串函数
- Javascript 日期对象简介
- Javascript 日期对象用途
- Date 对象属性和方法
- Javascript 数组是什么
- Javascript 创建数组
- Javascript 数组赋值与取值
- Javascript 数组属性和方法
- 分析网页 JavaScript Bundles 的几种方法
- 使用 DevTools 新增的 Issues 选项卡发现网页问题
- OpenCV绘制标记函数drawMarker()
- 【crossbeam系列】3 crossbeam-deque:work-stealing算法
- 【Rust日报】2020-08-21 RustConf研讨会在线举办
- 了解不同架构思维,赏析架构之美
- 【Rust日报】2020-08-22 google/autocxx - 高度自动化的rust调用c++,而且安全,时尚
- 【Rust日报】2020-08-24 理解 Rust 的切片
- 猿实战05——手把手教你拥有自己的代码生成器
- Java单元测试——容器内部测试
- Java单元测试——框架(三)——testNG
- Nginx系列:后端服务应用健康检测
- 那些大厂必问的Handler和Binder,有必要去研究么?
- 欢迎来到 TreeMap 的吐槽大会
- OMG,12 个精致的 Java 字符串操作小技巧,学它