【图论】树上差分 & 树上问题类

· · 算法·理论

例题

给定一棵 n 个节点的树,树有边权,有 m 次操作,每次查询给出两个节点,求他们在树上的距离。

Solution

当我们求出 xy 的 LCA 后,发现可以把这个距离看做两段:

x 到 LCA和 y 到 LCA 的距离,

计算出 dep[i] 表示 i 节点的深度,

dep[x]-dep[lca] 可表示 x 到 LCA 的距离,

输出 dep[x]-dep[lca]+dep[y]-dep[lca] 即可。

树上差分

xy 在树上的路径差分为:

$+y$ 到根的路径 $-$ LCA 到根的路径 $-$ LCA 的父亲到根的路径 ![](https://cdn.luogu.com.cn/upload/image_hosting/kbq09q07.png) *** **静态树上问题类** dfs 序以及树上差分的思想非常重要, 这些树上问题一般离线后都会又快又好写,建议使用离线的写法, 难点主要在于分析问题的具体性质,难以概括, 如果查询是树上的路径信息,可以使用树上差分的方法。 **例题** 给定一个 $n$ 个点的树,有 $m$ 次查询,每次查 $x$ 到 $y$ 路径上的点权和。 Q:序列上没有修改的时候我们怎么求区间和呢? A:利用前缀和差分。 Q:那树上呢? A:利用树上前缀和差分即可。 总时间复杂度 $\text{O}(n+m)

给定一个 n 个点的树,有 m 次查询,每次给两个点 x,y,求 x,y 之间的距离。

考虑预处理出 dep[x] 表示 x 到根的距离,

则利用树上差分的方法,

$x$ 到 LCA 的距离就是 `dep[x]-dep[lca]` 总时间复杂度 $\text{O}(n+m)

给一个 n 个点的树,有 m 次查询,每次给两个点 x,y,求 x 是否为 y 的祖先。

dfs 序可以用来表示子树关系,

如果 y 的 dfs 序位置被 x 的 dfs 序区间包含,

xy 祖先。

总时间复杂度 \text{O}(n+m)

动态树上问题类

需要掌握:

单点修改+链求和

链修改+单点求值

DFS 序很重要,处理子树时关注 DFS 序

例题

给定一棵 n 个节点的树,有点权,

m 次操作,每次会修改 x 点的权值,或者查询 x 所在子树的点权和。

A:

使用 DFS 序的转换,则一个点的子树可以通过 DFS 序转换成一段连续的区间,

问题变为单点修改 + 区间求和,使用树状数组即可解决。

总时间复杂度 \text O(n+m\log n)

给定一棵 n 个节点的树,有点权,

m 次操作,每次会修改 x 点的权值,或者查 xy 的路径的点权和。

A:

通过树上差分,将路径和变为查询 x 到根的路径和,

考虑每次修改 x 时影响哪些点到根的路径和,

影响范围为 x 的子树内答案,

则问题转换为单点查询 + 子树加,

使用 DFS 序的方法,变成单点查询 + 区间加

总时间复杂度 \text O(n+m\log n)

给定一棵 n 个节点的树,有点权,

m 次操作,每次会把 xy 路径上所有点的权值加上 z,或者查询点 x 的权值。

A:

通过树上差分,将路径和变为查询 x 到根的路径和,

考虑每次修改 x 时影响哪些点到根的路径和,

影响范围为 x 的子树内答案,

于是我们将 x 到根加的时候,实际上将 x 点权进行修改,

查询 x 的值时,实际上查询 x 的子树和,

通过 DFS 序的方法变为单点修改 + 区间求和。

总时间复杂度 \text O(n+m\log n)