浅谈 DFS 序的基础应用
注:以下例题的修改和查询操作都是与树的点权有关,若与边权有关也是类似的做法只需要在细节上略微修改即可。
例题 1
$n$ 个节点的树,$m$ 次操作,单点加,子树求和,$n,m \le 5 \times 10^6$。
DFS 序转化为序列上单点加,区间求和。
例题 2
$n$ 个节点的树,$m$ 次操作,子树加,单点求值,$n,m \le 5 \times 10^6$。
DFS 序转化为序列上区间加,单点求和。
例题 3
$n$ 个节点的树,$m$ 次操作,子树加,子树求和,$n,m \le 5 \times 10^6$。
DFS 序转化为序列上区间加,区间求和。
例题 4
$n$ 个节点的树,$m$ 次操作,路径加,单点求值,$n,m \le 5 \times 10^6$。
树上差分,将修改转化为路径上两个端点加,LCA 和 LCA 的父亲减,查询转化为子树求和。
DFS 序转化为序列上单点加,区间求和。
例题 5
$n$ 个节点的树,$m$ 次操作,单点加,路径求和,$n,m \le 5 \times 10^6$。
将查询转化为路径上两个端点到根的链的和,减去 LCA 和 LCA 的父亲到根的链的和。
注意修改需要差分保证只对子树内部的节点到根的链产生贡献。
DFS 序转化为序列上单点加,区间求和。
例题 6
$n$ 个节点的树,$m$ 次操作,路径加,子树求和,$n,m \le 5 \times 10^6$。
修改和 例题 4 一样转化,查询考虑以 $u$ 为根的子树内的每个点 $v$ 的差分数组 $d[v]$ 的贡献:
$d[v] \times (dep[u]-dep[v]+1) = d[v] \times (dep[u]+1) - d[v] \times dep[v]$,因此分别维护 $d[v]$ 和 $d[v] \times dep[v]$ 即可。
DFS 序转化为序列上单点加,区间求和。
例题 7
$n$ 个节点的树,$m$ 次操作,子树加,路径求和,$n,m \le 5 \times 10^6$。
查询和 例题 5 一样转化,修改考虑以 $u$ 为根的子树加 $w$ 对子树内每个点 $v$ 到根的链的贡献:
$w \times (dep[u]-dep[v]+1) = w \times dep[u] - w \times (dep[v]-1)$,因此分别维护 $w$ 和 $w \times dep[u]$ 即可。
注意修改仍然需要保证只对子树内部的节点到根的链产生贡献。
DFS 序转化为序列上单点加,区间求和。
例题 8(或者说是一个思考)
下面这三个问题仅靠 DFS 序可做吗?
1、单点加,子树加,路径加,单点求值,子树求和
2、单点加,子树加,单点求值,子树求和,路径求和
3、单点加,子树加,路径加,单点求值,子树求和,路径求和
前两个问题实际上是上面某些例题的结合体,显然能做。
DFS 序的强大之处在于将每棵子树对应一个区间,所以单点加,单点求值,子树加,子树求和都能做。
但是路径并不能在 DFS 序上表示成一个区间,所以只有路径加或者只有路径求和的情况可以通过差分等方法转化成一个区间。
但是如果同时出现路径加和路径求和仅靠 DFS 序确实无能为力……
所以第三个问题怎么做?可以考虑树剖 $log^2$ 求解。
如果 $n,m \le 5 \times 10^6$ 呢?可以用静态 LCT 一个 $log$ 求解(toptree 其实也是可以做到一个 $\log$ 但是带个 $100$ 的常数……)。
练习题:
#144. DFS 序 1(同 例题 1)
#145. DFS 序 2(同 例题 3)
#146. DFS 序 3,树上差分 1(同 例题 4 与 例题 6 的结合体)
#147. DFS 序 4(同 例题 5 与 例题 7 的结合体)
To be continued...