树上差分 学习笔记

发布时间 2023-04-19 10:26:42作者: dbxxx

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

树上点差分

记 \(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)\) 加上其所有子节点的权值就可以还原出 \(a(u)\)。

所以 dfs 一下就都能求出来了。

树上边差分

记 \(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\) 为根的子树内所有边权的和。

dfs 一下即可。

例题