dfs序与树链剖分

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

dfs序

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

时间戳

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

dfs序的性质

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

树链剖分

可以解决的问题

对于树上两个节点 u,vu, vu,v
1、将路径 uuuvvv 上的点都加上一个值
2、求路径 uuuvvv 所有点的权值和
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]

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值