找带权重心的常见套路无非是从根节点开始考虑重心能不能向儿子移动,然后用点分治优化。唯一要解决的就是怎么通过当前点的权值快速算出儿子节点的权值。
考虑令 \(f(x)\) 表示沿边 \(u\rightarrow v\) 移动了 \(x\) 长度后的权值(其中 \(s_i\) 表示 \(\mathrm{dist}(i,x)\)):
\[f(x)=\sum_{i\in t_v}a_i(s_i-x)^{\frac{3}{2}}+\sum_{i\not\in t_v}a_i(s_i+x)^{\frac{3}{2}}
\]
设 \(u\rightarrow v\) 长为 \(w\),现在要做的就是比较 \(f(0),f(w)\) 的大小关系。
考虑重心在 \(u\) 的儿子 \(v\) 的子树中,那么对于其他所有的 \(u\) 的儿子 \(w\),重心由 \(u\) 向 \(w\) 移动任意长度,权值都会变大,而向 \(v\) 移动才有可能变小,也才有可能存在更优的解。
现在要求的其实就是 \(f(x)\) 的上下趋势了,因为 \(f(x)\) 是下凸函数(不难证明),所以可以考虑求导,即求 \(f(\Delta)-f(0)\) 表示从 \(u\) 开始移动一段极小的长度,权值的变化量,根据上述规定只有权值变化量为负的才有可能存在更优的答案,也最多只有一个儿子变化量为负。
所以最终要求的就是 \(f‘(0)\),即:
\[f‘(x)=\frac{3}{2}\left(-\sum_{i\in t_v}a_i\sqrt{s_i-x}+\sum_{i\not\in t_v}a_i\sqrt{s_i+x}\right)
\]
带入 \(x=0\) 得 \(f‘(0)=\frac{3}{2}\left(-\sum_{i\in t_v}a_i\sqrt{s_i}+\sum_{i\not\in t_v}a_i\sqrt{s_i}\right)\),这玩意可以暴力求,因为点分治最多 \(\log n\) 层,所以复杂度为 \(O(n\log n)\) 。