#146. DFS 序 3,树上差分 1

题面

代码

首先明确,差分是对于全局的,而不是对于局部的。树上差分实现上又与序列差分有所不同,但实质就是将子树放进一段连续的区间。此题用到的是点的差分,注意将初值也看作差分!注意差分中无用的部分必须抵消,不然会影响前面!

还是利用朴素的\(dfs\)序(保证每个点只在序列中出现一次)。

操作\(1\):因为是修改树链,所以我们在两点分别加\(x\);又因为是从下往上差分(树的性质,除根节点外每个结点都有唯一的父亲),所以在它们的最近会合处\((LCA)\)会多加一次,再往上会多加两次(不在简单路径上)。对应地减去\(x\)就能解决。

操作\(2\):查询点的权值,只有它的子树会影响它的权值。子树中编号最大的点就是这段连续区间的末端,而开头就是当前点,那么总差分值相减就出来了。

操作\(3\):观察暴力做操作\(2\)的实现,发现子树中每个点的贡献是它与根的深度差\(+1\)(作用到的点数,每层是一个,性质已经提过)。根据乘法分配律,设当前点为\(u\),将式子拆开来:

\(\sum_{u=1}^n(deap[u]-deap[root]+1)*val[u]\)

\(=\sum_{u=1}^ndeap[u]*val[u]-(deap[root]-1)*val[u]\)

其中\(val\)是每个点的差分值,其中\(deap[root]-1\)是个定值,那么后者根据\(2\)操作可以直接计算,前者只需再开一个树状数组维护深度乘权值就可以支持查询了。

代码明天补。

\(O(mlogn)\)

你可能感兴趣的:(#146. DFS 序 3,树上差分 1)