P3369 【模板】普通平衡树(FHQ Treap树构建和解析)
题目描述
您需要写一种数据结构(可参考题目标题),来维护一些数,其中需要提供以下操作:
- 插入 x 数
- 删除 x 数(若有多个相同的数,应只删除一个)
- 查询 x 数的排名(排名定义为比当前数小的数的个数 +1 )
- 查询排名为 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
说明/提示
【数据范围】
对于 100% 的数据,1≤n≤105,∣x∣≤107
构建树:
对FHQTreap树进行构建:
FHQ Treap树是最后形态由键值和优先级决定。它的高明之处是所有操作都只用到了分裂和合并这两个基本操作,这两个操作的复杂度都为O(log2 n)。
前置知识:
C++
二叉搜索树
的基本性质,下面会讲二叉堆
二叉树搜索树是左节点小于根节点,根节点小于右节点。
用中序遍历可以看到是一个单调递增的序列。
二叉堆:
堆有大根堆和小根堆之分。
大根堆是根节点>左节点and 根节点>右节点;小根堆相反;
大根堆和小根堆一般上一层是满二叉树。这时会提高搜索的效率,时间复杂度减少。O(log2n)
有了以上的知识点:
对题目进行分析:
1、二叉树需要有左右节点。
2、要有一个键值,随机变量。
3、左右节点+本身的大小(这时在排名上有很大的用处)
代码如下:
struct Node {int ls, rs; // 左右 子节点 int key, pri; // key为值 pri 为随机的优先级int size; // 当前节点为根的子树的节点数量,用于求第k大和排名
}t[M];
核心:
1.插入节点