小清新数据结构题

首先我们要发现一个性质,对于每一棵树,我们换了一个根(把原本根的某个儿子(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}^nsum_{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 (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]) * S[i] ]

(sum - 1)直接维护,(sum S[i])用动态点分治来维护,后面那一堆我们可以根据(sum S[i])来维护,于是我们就做完了

原文地址:https://www.cnblogs.com/bcoier/p/11618363.html