4.3 CW 模拟赛 T2. 笛卡尔树
前言
也算比较充分地休息了, 好好学
思路
好像不少见到这种类型的问题, 不过一般都是子问题, 很少见到这种直接考的
那么就基于这道题看下有什么性质
首先是假设我们当前要在现在的基础上对 \(a_i, a_{i + 1}\) 进行交换, 不难发现直接做不好讨论, 不妨分两类处理
我们首先讨论 \(a_i < a_{i + 1}\) 的情况, 然后另外一种显然是相似的
首先 \(a_i\) 没有右子树, 可能是 \(a_{i + 1}\) 的左儿子或者 \(a_{i + 1}\) 的左子树的一个点的右儿子
交换后, \(a_i\) 进入了 \(a_{i + 1}\) 的右子树
\(a_i\) 的左子树的所有点深度减一;
对于 \(a_{i + 1}\) 的右子树中的一个点, \(a_i\) 会作为这个节点的左儿子, 这个节点原本的左子树会作为 \(a_i\) 的右子树, 深度加一
那么我们现在把问题简化成了
- 找到 \(a_i\) 的父亲, 及
- 父亲是 \(a_{i + 1}\)
- 找父亲的左子树大小
- 父亲是 \(a_{i + 1}\) 的左子树中的一个点
- 找父亲的右子树大小
- 父亲是 \(a_{i + 1}\)
- 找到交换之后, \(a_i\) 的父亲
- 父亲是 \(a_{i + 1}\)
- 找父亲的右子树大小
- 父亲是 \(a_{i + 1}\) 的左子树中的一个点
- 找父亲的左子树大小
- 父亲是 \(a_{i + 1}\)
需要一些绘图
画着画着发现找 \(dep\) 变化为 \(1\) 的区间可以去找 \(a_i\) 往前第一个比他大的节点和 \(a_{i + 1}\) 往后第一个比 \(a_i\) 大的节点
怎么做
首先有一个关键性质:「笛卡尔树的子树对应序列上的一段区间」, 因此考虑线段树维护深度
然后发现顺手维护一下权值就可以找 \(a_i\) 往前第一个比他大的节点和 \(a_{i + 1}\) 往后第一个比 \(a_i\) 大的节点, 相应维护深度即可
这个是一种别样的线段树上二分, 但是无伤大雅
总结
像这种跳进跳出的问题往往先规定方向和类型
然后尝试把问题简化成找某个性质的点的问题
画图的时候一定要注意图的合法性

浙公网安备 33010602011771号