FHQ Treap
简介
FHQ Treap和普通的Treap都是一个二叉搜索堆,其同时满足二叉树的性质(左子树的权值小于等于当前节点权值,右子树权值大于当前节点权值)和堆的性质(对于小根堆,当前节点的优先级是堆中最小的)。
FHQ Treap与一般的Treap的不同之处主要在于:
- 不用旋转,用split和merge来为维护堆的优先级。
- 能够可持久化。
操作
FHQ Treap的核心操作是split和merge,其他的操作均以这两个操作为基础进行。
下面所述操作的数据如下所示:
struct node {
int val, rnk, lc, rc, size;
}tree[nmax];
val表示节点的权值,用来维护二叉搜索树的性质;rnk表示节点的权值,用来维护堆的性质。lc和rc分别表示节点左子树和右子树的编号,size表示节点的大小(包括本节点在内)。
split
split要实现的是将一颗Treap分为两颗Treap,其中左Treap(以 a a a为根节点)中节点权值均小于等于目标值val,右Treap(以 b b b为根节点)中节点权值均大于目标值val。
给定根 r t rt rt,如果 t r e e [ r t ] . v a l ≤ v a l tree[rt].val \leq val tree[rt].val≤val,那么说明 r t rt rt及其左子树均可以划分给左树 a a a的左子树,接下来只需要考虑左树 a a a的右子树是什么。这时问题可以变为:对于给定的根 t r e e [ r t ] . r c tree[rt].rc tree[rt].rc(因为 r t rt rt的左子树已经划分给了 a a a),按照目标权值 v a l val val将其划分为以 t r e e [ a ] . r c tree[a].rc tree[a].rc和右树 b b b的两颗Treap。问题可以递归求解。
考虑另一种情况,如果 t r e e [ r t ] . v a l > v a l tree[rt].val > val tree[rt].val>val,那么说明 r t rt r