dfs序与树链剖分

本文介绍了深度优先搜索(DFS)的概念,包括dfs序的定义、时间戳的特性,以及其在树链剖分和LCA查询中的应用。重点讲解了如何利用dfs序进行线段树操作,以及解决路径加权、子树更新等问题。还涉及了重儿子、轻儿子和重链剖分的概念及其在算法中的作用。
摘要由CSDN通过智能技术生成

dfs序

dfs序是对于一棵树而言,我们dfs的顺序。
主要目的是用于对一棵树上的结点形成一个数组,可以用于建线段树等操作。
在dfs序中,每个节点只出现一次(欧拉序每个节点出现两次)。
在这里插入图片描述
比如者一棵树的dfs序为 ABCDEF

时间戳

每个节点第一次被访问的时间

dfs序的性质

父节点的时间戳小于子节点的时间戳

树链剖分

可以解决的问题

对于树上两个节点 u , v u, v u,v
1、将路径 u u u v v v 上的点都加上一个值
2、求路径 u u u v v v 所有点的权值和
3、将节点 u u u 为根的子树都加上一个值
4、求节点 u u u 为根的子树所有点的权值和

重儿子

一个节点的子节点所在的子树中节点最多的子节点为重儿子

轻儿子

除重儿子以外的所有儿子

重链剖分

以重儿子优先的dfs序,将一棵树剖分为多个重链。每个重链以轻儿子开头,其余点都是重儿子。
对于树链剖分,我们需要记录以下几个值
d f n [ x ] dfn[x] dfn[x] dfs序
f a [ x ] fa[x] fa[x] 父节点
s z [ x ] sz[x] sz[x] 节点大小
t o p [ x ] top[x] top[x] 所在链的首节点
s o n [ x ] son[x] son[x] 重儿子
d e p [ x ] dep[x] dep[x] 深度

我们需要进行两次dfs,第一次求出 f a   s z   s o n   d e p fa \ sz \ son\ dep fa sz son dep 的信息,第二次dfs求出 t o p   d f n top \ dfn top dfn

求LCA

因为我们知道了每个节点的深度和所在重链的情况。所以我们可以这样考虑。
当两个点在同一条重链的时候,此时的 l c a lca lca 即为深度较浅的点。
当两个点不同一条重链的时候,此时让所在重链首节点较深的点往上跳,跳出它所在的这一条重链。

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序的时间戳建立线段树,然后我们在两个点的 L C A LCA LCA 的过程中更新线段树即可。
操作3、4
我们直接用dfs序和节点 x x x 的子树大小即可更新线段树,更新区间为
[ d f n [ x ] , d f n [ x ] + s z [ x ] − 1 ] [dfn[x], dfn[x] + sz[x] - 1] [dfn[x],dfn[x]+sz[x]1]

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值