树上差分 学习笔记

在树上对链上所有点 / 边加,最后查询每个点 / 边的权值。

树上点差分

\(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 一下即可。

例题

posted @ 2023-04-19 10:19  dbxxx  阅读(47)  评论(0编辑  收藏  举报