若
split/merge像两块突然递来的乐高,先完成 课前零食:从排好队到会分身的树。其中从有序数组、普通 BST 一直走到pull、分裂与合并,并配有可操作实验室。
掌握无旋 Treap(FHQ Treap)的两条原语 split/merge,维护动态有序多重集的插入、删除、第 k 小、排名及极值删除。
前置:BST、随机化、子树大小。
split(root,key) 应保证两棵树满足什么键范围?merge(a,b) 需要什么前置条件?FHQ Treap 不围绕某节点旋转,而是把所有操作归结为:
节点同时满足键的 BST 顺序和随机优先级的堆顺序。size 在每次改儿子后 pull。重复值可每次建独立节点,也可存 count;附件前者更统一。
rand() 低位和对抗数据。<x、==x、>x,只删等值树一个节点。kth 前确认 $1\le k\le size(root)$。时间轴只前进、不删除,所以在每次询问前补插新元素,然后沿 left_size 选择第 i 小。Treap 中序序列始终是当前多重集排序结果;kth 根据左子树元素数排除整棵子树,归纳能到达排序序列第 k 项。期望复杂度 $O((M+N)\log M)$。
for query_index i in 1..Q:
while inserted < u[i]: root = insert(root, next_value)
output kth(root, i)
(客户编号,优先级),支持弹出最高优先级或最低优先级客户;空时输出 0。插入时按优先级分裂并夹入新节点。删除极值先找到键,再把 <key、==key、>key 分开,丢弃等值根并合并其子树后接回。分裂/合并保持中序键序与优先级堆序,所以每步后仍是合法 Treap;中序极端节点正是优先级极值。每操作期望 $O(\log n)$。
insert(id, priority): split by priority; merge(left, new_node, right)
pop_min/max:
find extreme node by left/right pointers
output its id
erase one node with that priority via splits and merges
FHQ Treap 可按键持久化:split/merge 时路径复制;也可按排名成为隐式序列树,见下一节。若要求严格最坏 $O(\log n)$,需红黑树、AVL 等确定性结构。
与 multiset 随机对拍插删、排名、kth。主动插入递增键检查树高分布;固定随机种子便于复现失败。