CF708C题解

挺简单的一道数据结构。。。

首先考虑这个“改造”的本质,很明显是把一颗子树塞到了另一个节点下面。

考虑一个节点可能成为重心的条件。条件很明显是只有一颗子树的大小大于 \(\frac n 2\),否则一定不行。

考虑将这个子树的一个子树塞到我的别的子树中去。假设最大的子树大小是 \(x\),最小的子树大小是 \(y\),那么必须要找到 \(x\) 的一颗子树 \(s\) 满足 \(x-siz[s] \leq \frac n 2 \And y+siz[s] \leq \frac n 2\)

问题转化为询问 \(x\) 是否有一个子树满足 \(x-\frac n 2 \leq siz[s] \leq y+\frac n 2\),这个问题可以由树套树来解决。

另一个操作就是在换根时,维护子树对应的大小。注意到换根只会对应到一条边,只会改变这两个节点的 \(siz\) 值,所以直接维护就好了。

复杂度是 \(O(n\log^2n)\),但是有没有更简单的方法?

考虑到一个节点的 \(siz\) 只有 \(siz\)\(n-siz\) 两种,并且一个节点的子树大小为 \(n-siz\) 时只有可能在 \(u\)\(1\) 的路径上,考虑直接询问 \(dfn\) 序上区间的权值在给定权值区间中数的数量,最后减去这一段。

至于这一段,在换根的时候可以开一颗权值树来询问。

离线下来做这个相当于二维前缀和,使用树状数组可以轻松做到 \(O(n\log n)\) 小常数。

posted @ 2022-01-25 12:04  Prean  阅读(42)  评论(0编辑  收藏  举报
var canShowAdsense=function(){return !!0};