参考:笛卡尔树学习笔记 - 作业部落 Cmd Markdown 编辑阅读器
笛卡尔树是一种二叉树,每个节点维护两个值,一个是需要满足二叉搜索树性质的val,另一个是需要满足堆性质的priority。
在val排好序的情况下,笛卡尔树可以在线性时间内构建。一个有用的结论是,对于一组固定的节点,构造出的笛卡尔树是唯一的。
例如下图中,数组下标是val,元素值是priority
构建方法很简单,先将节点按照val排序,然后挨个从右边插入(这就是为什么代码中r[0]的值也是rt),同时用单调栈维护右链(递增或递减),然后插入节点时弹出的链变为节点的左子树,再将节点连在右链下。
http://poj.org/problem?id=1785
1 |
|
拓展
再看一道难一点的题https://codeforces.com/contest/1220/problem/F
官方做法是用线段树,维护每次移动后每个节点的祖先数目。然后最多的祖先数目就是树深。现在考虑怎么用笛卡尔树来做。
看博客补充了一个笛卡尔树的黑科技:在插入节点时不断维护树的高度。原理很清晰,我们维护右链上每个节点的子树的深度,在插入节点时看它冲掉了哪些右链节点,在这些节点里面取最深的+1,就是新节点子树的深度;如果一个都没有冲掉,那么该节点的位置(链长)就是它的子树深度。注意这里子树深度说的是,这个子树里最深的点在整棵树中的深度。这样一来,我们就可以维护全局最小点两侧不断插入节点后的树深。整棵树的深度就是两侧较大的再+1。枚举全局最小点应该在哪个位置即可。
1 |
|