一个套路题,因为不会这个套路所以记一记。
首先题面的式子可以改写成这样:\(f(x)=\sum\limits_{y\in son(x)} sum_y*(sz_x-sz_y)+(sz_x+1)*w_x\)
然后一次\(1\;x\;v\)的修改会影响到点有在\(x\)子树内且与\(x\)的距离\(\leq 2\)的点,\(x\)本身,和\(x\)的祖先。
计算在\(x\)子树内且与\(x\)的距离\(\leq 2\)的点和\(x\)本身的贡献,推推式子发现可以直接打标记维护。
对于\(x\)的祖先\(y\),贡献是\((sz_y-sz_x)*V\),其中\(V=v*count(x,2)\),\(count(x,2)\)表示和\(x\)距离\(\leq 2\)的点的数量。
于是就有这样一个套路
树链剖分,如果\(x\)是个轻儿子,暴力加贡献。否则就在\([dfn[fa[x]],dfn[top[x]]]\)集体加。
后面这个操作在重链上维护线段树,线段树每个叶子维护\(base=sz[rnk[l]]-sz[son[rnk[l]]]\),如果没有\(son\)那\(base=0\),和一个\(tag\)累计要乘多少,每次修改修改\(tag\),询问把经过的\(tag\)累加再乘\(base\)就行了。