本文同步发表在洛谷博客。
什么是 FHQ-Treap?
平衡树上存放两个信息,权值 \(val\) 以及随机索引 \(key\)。值满足二叉搜索树性质,随机值索引满足堆的性质,通过结合二叉搜索树和二叉堆的性质来使树平衡。至于这里用的是大根堆还是小根堆,不重要。
当权值 \(val\) 的数值情况不可控时,如果保证索引 \(key\) 为随机,树的期望深度为 \(\log n\)。
通常的平衡树维护平衡的方法是旋转,而 FHQ-Treap 则是用分裂和合并来实现的。
详解 FHQ-Treap
FHQ-Treap 存放的节点信息
首先,有必不可少的权值 \(val\) 和随即索引 \(key\)。其次为了维护树的结构,肯定要有左节点编号 \(ls\) 以及右节点编号 \(rs\)。当然,为了求排名之类的东西,我们还会维护一个子树大小 \(sz\)。由于要维护的信息较多,这里采用结构体进行维护。
struct FHQ_Trp{int ls,rs,val,key,sz;}tree[N];
FHQ-Treap 的分裂操作
分裂,即 Split,是 FHQ-Treap 中必不可少的一环。
分裂方法有两种:
- 按值分裂:把树拆成两棵树,拆出来的一棵树的值全部小于等于给定的值,另外一棵树的值全部大于给定的值。
- 按大小分裂:把树拆成两棵树,拆出来的一棵树的值全部等于给定的大小,剩余部分在另外一颗树里。
通常来说,当 FHQ-Treap 作为正常平衡树使用时,采用按值分裂;维护区间信息时,用按大小分裂。