树上差分 学习笔记
在树上对链上所有点 / 边加,最后查询每个点 / 边的权值。
树上点差分
记 \(a(u)\) 为点 \(u\) 的权值,记 \(d(u)\) 表示 \(a(u) - \sum_{v \in \operatorname{son}(u)} a(v)\)。
现在,我们对 \(s \rightsquigarrow t\) 这条链整体加上 \(x\)。
定义 \(s\) 和 \(t\) 的 LCA 是 \(p\)。则这个操作可以拆成三步:
- 对 \(s \rightsquigarrow p\) 这条链整体加上 \(x\)。
- 对 \(p \rightsquigarrow t\) 这条链整体加上 \(x\)。
- 对点 \(p\) 单点减去 \(x\)。
三步对差分数组的影响分别是:
- \(d(s)\) 多了 \(x\),\(d(\mathrm{fa}(p))\) 少了 \(x\)。
- \(d(t)\) 多了 \(x\),\(d(\operatorname{fa}(p))\) 少了 \(x\)。
- \(d(p)\) 少了 \(x\),\(d(\operatorname{fa}(p))\) 多了 \(x\)。
综合影响为:
- \(d(s)\) 多了 \(x\)。
- \(d(t)\) 多了 \(x\)。
- \(d(p)\) 少了 \(x\)。
- \(d(\operatorname{fa}(p))\) 少了 \(x\)。
这样链加就变成了四个单点加。所有链加结束后,将 \(d(u)\) 加上其所有子节点 \(v\) 的权值 \(a(v)\) 就可以还原出 \(a(u)\)。
为此我们应该先知道儿子的 \(a\) 再知道父亲的 \(a\),对树进行 dfs,对于每个 \(u\) 先把其所有子节点的 \(a\) 计算好(方法就是直接 dfs(v)
),再计算 \(a(u)\) 即可。
树上边差分
记 \(a(u, v)\) 为边 \((u, v)\) 的权值,记 \(d(u) = a(u, \operatorname{fa}(u)) - \sum_{v \in \operatorname{son}(u)}a(u, v)\)。
现在,我们对 \(s \rightsquigarrow t\) 这条链整体加上 \(x\)。
定义 \(s\) 和 \(t\) 的 LCA 是 \(p\)。则这个操作可以拆成两步:
- 对 \(s \rightsquigarrow p\) 这条链整体加上 \(x\)。
- 对 \(p \rightsquigarrow t\) 这条链整体加上 \(x\)。
两步对差分数组的影响分别是:
- \(d(s)\) 多了 \(x\),\(d(p)\) 少了 \(x\)。
- \(d(t)\) 多了 \(x\),\(d(p)\) 少了 \(x\)。
综合影响为:
- \(d(s)\) 多了 \(x\)。
- \(d(t)\) 多了 \(x\)。
- \(d(p)\) 少了 \(2x\)。
链加就变成了三个单点加。
最后,\((u, \mathrm{fa}(u))\) 这条边的权值为 \(d(u)\) 加上 \(u\) 和其所有儿子之间的边权和,也即 \((v, \mathrm{fa}(v))\) 的权值和,其中 \(v\) 是 \(u\) 的儿子。
dfs 一下即可。