版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/weixin_37517391/article/details/82969226
Count on a Treap
题目来源
Codechef Feb 2014 COT5
https://www.codechef.com/problems/COT5
问题提出
什么是Treap
- 是一颗二叉搜索树,每个节点拥有 属性.
- 是一颗堆,每个节点拥有 属性
问题
-
次操作,三种类型,要求维护"大根Treap"
- ,插入 为 为 的点.
- ,删除 为 的点
- ,询问 为 的两点在 中的距离.
保证 , 均不相同.
问题解答
我们以 为下标,将这个树按中序遍历展开.
显然 之间最大的 最大的点就是两点的 .
证明:首先 一定在区间 之间,不然 将位于 的同一侧,这不可能.其次权重最大的点一定是这颗子树的根节点,这个点一定是祖先,如果它不是 的话,那么它的 将大于或小于 形成的子树中所有的点的 ,也就是说它不在区间 之间,矛盾.
至此,用线段树可以轻松维护 .
那么如何维护一个点在树上的深度呢?
根据Treap的特殊性质,我们知道每个点的 一定小于他父亲的 .
从这个点到根节点的祖先链上的 是不断递增的.
这里有一个非常特殊的性质,在序列上就是从这个点往两侧各找一个直接的递增子序列,那么序列上的点都是他的祖先.
这个性质基于这样一个事实:每个点左右两侧的第一个大于它 的点,都是这个点的一个祖先.因为其中一个点是它的父亲,而另一个点…自己画图观察一下就好了.
因此两个递增序列的长度和就是它到根的距离.
如何维护某一个点向右的直接递增序列呢.也是使用线段树,参考我的另一篇博客,楼房重建.