首页 > 其他分享 >树链剖分

树链剖分

时间:2023-03-09 17:47:35浏览次数:29  
标签:剖分 top belong dfs 树链 深度 区间 节点

介绍

解决树上问题的时候,对于路径问题我们会想到树分治、启发式合并。对于子树问题我们会想到在 dfs 序上转化为序列问题方便维护。

那么对于路径问题,能不能也转化为序列问题?

可以的。

这就是树链剖分在做的事情:把一棵树划分为若干段 dfn 连续的区间,使得某一个路径可以被拆分为 \(O(\log n)\) 个 dfs 序区间。(为了方便这里把拆出来的叫区间,原来的路径叫链)

image

虽然一开始给你的树不一定能够做到这一点,但是我们对 dfs 的顺序进行改变,可以做到这一点。考虑每次 dfs 到一个节点之后优先向其重儿子去遍历。

我们来证明一下上面的两个结论正确性。

首先,一棵树被划分为段 dfn 连续的区间:显然,某一个节点和父亲不连续说明它不是重儿子,于是不会被分到一起。

其次,一条路径被划分为 \(O(\log n)\) 段链:首先考虑某个点到根节点的路径。考虑现在有一个从 \(1\) 开始朝着另一端行走的人,它跳到另一个区间上花费 \(1\) 的代价。考虑其子树大小,每次一定减去至少一半。因此一共花费 \(O(\log n)\) 的代价。再考虑一般的路径,显然和其同阶。

考虑我们如何找到这些拆成的区间。我们有初始节点 \((x,y)\) 代表链的两端。然后不断选择所在区间深度较大的那一个点(假设是 \(x\)),找到链顶 \(top\),对 \((top, x)\) 区间做贡献,然后 \(x\) 跳到 \(top.fa\)。注意区间深度指的是根节点到这条链要穿过几条链,因为如果使用的是点的深度,那么上图的 \(5 \rightarrow 8\) 因为 \(5\) 深度较大要跳,但是它已经不能再跳了。

伪代码:

void gx(int x, int y) {
	while(1) {
		if(x.belong.deep < y.belong.deep) swap(x,y);
		if(x.belong != y.belong) {
			update(x.belong.top, x); //dfn 连续段
			x = fa[x.belong.top];
		}
		else break;
	}
	if(x.depth > y.depth) swap(x, y);
	update(x, y);
}

如何进行树剖

考虑需要维护什么。

  • 子树大小 -> 重儿子。
  • dfs 序,以及每个 dfs 序对应什么节点。
  • 每个节点属于什么链上。
  • 链顶和底。
  • 每条链的深度。
  • 点的深度。
  • 点的父亲。

做两次 dfs 进行维护。

第一次 dfs 维护什么:

  • 子树大小 -> 重儿子。
  • 点的深度。
  • 点的父亲。

第二次 dfs 维护什么:

  • dfs 序,以及每个 dfs 序对应什么节点。
  • 每个节点属于什么链上。
  • 链顶和底(但是我们发现好像不太需要维护链底)。
  • 每条链的深度。

标签:剖分,top,belong,dfs,树链,深度,区间,节点
From: https://www.cnblogs.com/Zeardoe/p/17199341.html

相关文章

  • 学习笔记:重链剖分
    重链剖分前置芝士:线段树,dfs序,LCA概念一个非叶子节点,他的儿子中子树大小最大的就是重儿子,否则就是轻儿子对于一条边,如果连接的子节点是重儿子,那么这条边就是重边,否则......
  • 树链剖分模板(为什么我的这么长???)
    #include<iostream>#include<cstdio>#include<cmath>#include<algorithm>#include<cstring>#definelidid<<1#defineridid<<1|1usingnamespacestd;l......
  • 树链剖分
    终于学到了树剖!!!前置知识:LCA,树形DP,DFS,邻接表,线段树。 树链剖分线段树的特点:区间修改,区间查询,线性;树上差分特点:单点修改,树形区间查询;现在,如果我们想进行树形区间修改......
  • 【YBT2023寒假Day14 C】字符串题(SAM)(树链剖分)(线段树)
    字符串题题目链接:YBT2023寒假Day14C题目大意对于一个字符串S定义F(S)是fail树上除了0点其它点的深度和。G(S)是S每个子串S'的F(S')之和。然后一个空......
  • 树链剖分详解
    树链剖分那么我们首先来了解一下他可以干什么。因为他的实现一般都要用到线段树,所以它可以进行:两点之间最短路修改两点之间最短路查询以某点为根节点的子树修改以某......
  • 树链剖分 学习笔记
    树链剖分学习笔记树链剖分(Treedecomposition),顾名思义,是一种将树剖分为若干条链,使得可以用数据结构维护树上信息的数据结构。树链剖分有多种意思,包括重链剖分、长链剖分......
  • 【CCCC】L2-030 冰岛人 (25分) 模拟题,二叉树链式存储,从底部向上
    problemL2-030冰岛人(25分)2018年世界杯,冰岛队因1:1平了强大的阿根廷队而一战成名。好事者发现冰岛人的名字后面似乎都有个“松”(son),于是有网友科普如下:iceland.JPG冰岛......
  • 长链剖分
    现在的情况是正在找一些比较轻量化的题单来写。长链剖分。我们知道树的链剖分有三个,重剖,长剖,还有一个不是很正统的实链剖分。重链剖分就是每次找子树最大的一个当做重儿......
  • 2019年ICPC南昌网络赛 J. Distance on the tree(树链剖分+主席树 查询路径边权第k大)
    DSM(DataStructureMaster)oncelearnedabouttreewhenhewaspreparingforNOIP(NationalOlympiadinInformaticsinProvinces)inSeniorHighSchool.Sowhen......
  • 长链剖分
    概述长链剖分通过把树剖成尽量长的多个链,高效地解决...我也不知道解决啥(长剖优化DP的东西在DP优化那边)。毕竟这个东西,不具备启发式分裂的复杂度。不过其还是有一......