小清新数据结构题
首先我们要发现一个性质,对于每一棵树,我们换了一个根(把原本根的某个儿子\(v_1\)记成新的根)
我们记这个树的权值和为sum,每个子树的权值和为\(S[i]\),对于每次换根,受影响的\(S[i]\)只有根本身和\(v_1\),并且满足:\(S[rt]->sum - S[v_1]\), \(S[v_1] -> S[rt]\)
于是我们能惊人的发现:\(\sum (sum - S[i]) * S[i]\)是一个定值!!!
把他拆开:\(sum * \sum S[i] - \sum S[i] ^ 2\)
而我们要求的正是\(\sum S[i] ^ 2\),于是我们只要维护\(sum * \sum S[i]\)
因为我们会修改权值,发现sum值很好维护,于是我们只需要维护\(\sum S[i]\)即可
我们假设以x为根,那么\(\sum S[i] = \sum (dep[i] + 1) * val[i] = sum + \sum dep[i] * val[i]\)
若我们不用重新求dep,柿子即化为:$\sum S[i] = sum + \sum val[i] * dis(i, x) $
这个式子就是动态点分治的模板了,但是我们其实还有一个问题:就是我们的那个定值(\(\sum (sum - S[i]) * S[i]\))要怎么求呢?
我们还是对每个点分开考虑:上述柿子的意义实际上是求出所有点的子树和 * (总的子树和 - 该点子树和)
我们分开考虑每一对点\((i, j)\)的贡献,即两个点被分在不同集合的个数*权值之积
于是这个式子其实可以转化为\(\sum_{i = 1}^n\sum_{j = i+ 1}^nval[i] * val[j] * dis(i, j)\)
把\(val[i]\)提前,我们得到:\(\sum_{i = 1} ^ n val[i] * \sum_{j = i + 1} ^ n val[j] * dis(i, j)\)
所以每一次修改(a[x] -> y),变化量即为\((y - a[x]) *\sum val[j] * dis(j, i)\)
这不就是\(\sum S[i]\)吗???
于是,我们就可以得到:
\(sum - 1\)直接维护,\(\sum S[i]\)用动态点分治来维护,后面那一堆我们可以根据\(\sum S[i]\)来维护,于是我们就做完了