[Procedure #14] P5666 [CSP-S2019] 树的重心

[Procedure #14] P5666 [CSP-S2019] 树的重心

[Start]

完美二叉树和链当然是很容易做的。那么一般的树,又该如何做呢?

观察

如果删除的边在直径上,新树的重心还在原先直径的边上(可能还有一个在直径旁边的一个相邻点)。

如果删除的边不在直径上,那么有一边重心不变,另一半没有很好的性质。

好像这些玩意都没什么用,而且多个重心的情况还很麻烦。

[Hint] 求每个点作为重心的次数

假如我操作的是最大的子树,那么满足的是 \(mx-x\le (n-x)/2\),由于前者一定为整数,所以不加下取整也行,化为:\(2mx-2x\le n-x\),化为 \(x\ge 2mx-n\),除此之外次大的如果是 \(se\),那么 \(n-2se\ge x\)。否则如果操作的不是最大的子树,要满足 \(n-2mx\ge x\)。那么我们考虑统计这些东西,我们弄一个线段树或者树状数组然后换根 DP 即可。

现在考虑计算方式,全局的,随着 dfs 维护的树状数组,称为 B,访问到新节点就加入的树状数组称为 A:

  • 如果最大点是父亲子树,在 A 上差量法准确计算贡献二,然后进入 x 的时候先在 B 上计算贡献一,我们再在 A 上用差量法去除贡献一

  • 如果最大点不是父亲子树,我们进入 x 时先在 B 上计算贡献二,然后在 A 上利用差量法去除 mx 的贡献二,然后在 A 上利用差量法准确计算 mx 的贡献一。

因此,我们存储 se 的时候可以只存 siz,存储 mx 的时候需要存储 mxid。

[Finish]

怎么说呢,这个题真不难,真是一点就通,所以如果不能找出合适的性质的时候,考虑转化贡献方式。

posted @ 2025-08-26 17:18  haozexu  阅读(9)  评论(0)    收藏  举报