dfs序
dfs序是对于一棵树而言,我们dfs的顺序。
主要目的是用于对一棵树上的结点形成一个数组,可以用于建线段树等操作。
在dfs序中,每个节点只出现一次(欧拉序每个节点出现两次)。

比如者一棵树的dfs序为 ABCDEF
时间戳
每个节点第一次被访问的时间
dfs序的性质
父节点的时间戳小于子节点的时间戳
树链剖分
可以解决的问题
对于树上两个节点 u,vu, vu,v
1、将路径 uuu 到 vvv 上的点都加上一个值
2、求路径 uuu 到 vvv 所有点的权值和
3、将节点 uuu 为根的子树都加上一个值
4、求节点 uuu 为根的子树所有点的权值和
重儿子
一个节点的子节点所在的子树中节点最多的子节点为重儿子
轻儿子
除重儿子以外的所有儿子
重链剖分
以重儿子优先的dfs序,将一棵树剖分为多个重链。每个重链以轻儿子开头,其余点都是重儿子。
对于树链剖分,我们需要记录以下几个值
dfn[x]dfn[x]dfn[x] dfs序
fa[x]fa[x]fa[x] 父节点
sz[x]sz[x]sz[x] 节点大小
top[x]top[x]top[x] 所在链的首节点
son[x]son[x]son[x] 重儿子
dep[x]dep[x]dep[x] 深度
我们需要进行两次dfs,第一次求出 fa sz son depfa \ sz \ son\ depfa sz son dep 的信息,第二次dfs求出 top dfntop \ dfntop dfn
求LCA
因为我们知道了每个节点的深度和所在重链的情况。所以我们可以这样考虑。
当两个点在同一条重链的时候,此时的 lcalcalca 即为深度较浅的点。
当两个点不同一条重链的时候,此时让所在重链首节点较深的点往上跳,跳出它所在的这一条重链。
int LCA(int x, int y){
while(top[x] != top[y]){
if(dep[top[x]] > dep[top[y]]) swap(x, y);
y = top[y];
y = fa[y];
}
return dep[x] > dep[y] ? y : x;
}
性质
一个重链的dfs序是连续的
如何解决上述四个操作
操作1、2
用dfs序的时间戳建立线段树,然后我们在两个点的 LCALCALCA 的过程中更新线段树即可。
操作3、4
我们直接用dfs序和节点 xxx 的子树大小即可更新线段树,更新区间为
[dfn[x],dfn[x]+sz[x]−1][dfn[x], dfn[x] + sz[x] - 1][dfn[x],dfn[x]+sz[x]−1]
本文介绍了深度优先搜索(DFS)的概念,包括dfs序的定义、时间戳的特性,以及其在树链剖分和LCA查询中的应用。重点讲解了如何利用dfs序进行线段树操作,以及解决路径加权、子树更新等问题。还涉及了重儿子、轻儿子和重链剖分的概念及其在算法中的作用。
1万+

被折叠的 条评论
为什么被折叠?



