基于随机优先级的自平衡二叉搜索树 Treap,作为“顺序容器”支持对序列进行对数时间的 split/join,并易于按需扩展维护额外信息。
> Description: A short self-balancing tree. It acts as a > sequential container with log-time splits/joins, and > is easy to augment with additional data. > Time:
-
结构与字段(据实现)
- Node:包含左右子指针
l, r,键值val,随机优先级y(构造时rand()),以及子树大小c(默认 1)。 cnt(Node* n):空指针返回 0,否则返回n->c。Node::recalc():按c = cnt(l) + cnt(r) + 1维护子树大小。
- Node:包含左右子指针
-
基本遍历
each(Node* n, F f):中序遍历(左-根-右),对每个结点的val调用回调f。
-
核心操作(顺序容器语义)
split(Node* n, int k):- 按“前 k 个元素”将树分为两棵(返回
{L, R})。 - 若左子树大小
cnt(n->l) >= k,则在左子树递归 split,并将结果右部接回n->l;否则在右子树以k - cnt(n->l) - 1递归并将结果左部接回n->r。 - 每次结构变动后调用
recalc()维护c。
- 按“前 k 个元素”将树分为两棵(返回
merge(Node* l, Node* r):- 按随机优先级
y合并两棵 Treap,较大y的结点为根;相应地递归合并其子树并recalc()。
- 按随机优先级
ins(Node* t, Node* n, int pos):- 先
split(t, pos),再将新结点n插入到中间:merge( merge(l, n), r )。
- 先
-
示例操作
move(Node*& t, int l, int r, int k):- 将区间
[l, r)从原位置移动到索引k:split(t, l)得到a与余部;再split(余部, r-l)得到区间段b与余下c;- 若
k <= l:t = merge( ins(a, b, k), c );否则:t = merge( a, ins(c, b, k - r) )。
- 将区间
-
复杂度
split/merge/ins等核心操作均为期望 O(log N)。