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

树链剖分

时间:2023-08-08 22:55:27浏览次数:50  
标签:sz 剖分 链头 儿子 树链 son 节点

目录

树链剖分

基础概念
重儿子:父节点的所有儿子中子树节点数目最多的节点
轻儿子:父节点除重儿子以外的节点
重边:父节点和重儿子连成的边
轻边:父节点和轻儿子连成的边
重链:由多条重边连接而成的路径
如下图,绿色边即为重边
image

性质
1.整棵树会被剖分成若干条重链(可以将单独的叶子节点看作一条重链)
2.轻儿子一定是每条重链的顶点
3.任意一条路径被切分成不超过 \(\log n\) 条链

用到的 5 个数组:

  • fa[u]:存节点 u 的父节点

  • dep[u]:存节点 u 的深度

  • son[u]:存节点 u 的重儿子

  • sz[u]:存以节点 u 为根的子树的节点个数

  • top[u]:存 u 所在的重链的顶点,即链头

利用两个 dfs 处理这五个数组(4 + 1)
(下面是用邻接表实现的)
dfs1 :预处理数组 dep、sz、fa、son,初始为 dfs1 (根节点, 0)
从根开始遍历每个节点,统计深度、父节点和节点数初值,最主要就是递归后判断重儿子的位置

void dfs1(int u, int f){//预处理dep、sz、fa、son
	dep[u] = dep[f] + 1;
	sz[u] = 1;
	fa[u] = f;
	for(auto v : e[u]){
		if(v == f) continue;
		dfs1(v, u);
		sz[u] += sz[v];
		if(sz[v] > sz[son[u]]) son[u] = v;
	}
	return ;
}

dfs2 :预处理数组 top,初始为 dfs2 (根节点,根节点)
首先赋值链头,如果没有重儿子直接返回,再 dfs 重儿子(重儿子的链头是当前的链头),最后遍历轻儿子,但是轻儿子的链头是自己

void dfs2(int u, int t){//预处理top
	top[u] = t;
	if(!son[u]) return ;
	dfs2(son[u], t);
	for(auto v : e[u]){
		if(v == fa[u] || v == son[u]) continue;
		dfs2(v, v);
	}
	return ;
}

相关资料

树链剖分法 - dx123

例题

求最近公共祖先

标签:sz,剖分,链头,儿子,树链,son,节点
From: https://www.cnblogs.com/Qiansui/p/17615616.html

相关文章

  • 树链剖分
    本文的树链剖分指的是长链剖分Part1:知识点树链剖分常用于解决下面的问题:修改树上两点之间的路径上所有点的值。查询树上两点之间的路径上节点权值的和/极值/其它(在序列上可以用数据结构维护,便于合并的信息)。下面给出一些定义:重儿子:表示一个节点的子节点中子树最大......
  • UOJ #284. 快乐游戏鸡题解(长链剖分+单调栈合并)
    UOJ#284.快乐游戏鸡题解(长链剖分+单调栈合并)题面一番战斗之后,程序猿被计算鸡们赶走了。随着垫子计算鸡一声令下:“追!”,于是计算鸡村全村上下开始乘胜追击。计算鸡们希望在新的一年到来之际给程序猿以重创,出掉这一年的恶气。可是程序猿一追就走,一走就跑,一跑就无影无踪。计算鸡......
  • 20230626-树链剖分+点分治
    20230626重链剖分计算每个节点子树大小,判断出每个点的重儿子优先遍历重儿子连边,并且按照DFS序重新编号特点:每条重链上的点编号是连续的每个点为根的子树内所有点的编号是连续的$\to$线段树需求:对于树上两点\(x,y\)路径上的所有点进行操作必然不能避免的事情......
  • 长链剖分
    类似于轻重链剖分,也有一种树链剖分方式叫做长链剖分,每次我们选子树深度最大的节点当做重儿子,注意这里子树深度是指一棵子树中所有结点的深度最大值。有以下性质:一个节点的\(k\)级祖先所在链的长度一定大于等于\(k\)。比较显然。因为如果小于\(k\)的话就会选从那个祖先到......
  • 树链剖分模板
    区间,边权描述松鼠爸爸为了让松鼠宝宝更熟悉地熟悉采松果的流程,为其定制了一颗“树”,树上有n个点,n-1条边(无环),每条边上都有一定数量的松果。松鼠爸爸为了让松鼠宝宝得到更多的松果,有m次操作,每次操作给定两个点x,y和一个add,在x点到y点的简单路径上所有......
  • BZOJ 2243: [SDOI2011]染色 树链剖分+线段树
    2243:[SDOI2011]染色TimeLimit: 20Sec  MemoryLimit: 512MBSubmit: 7623  Solved: 2855[Submit][Status][Discuss]Description给定一棵有n个节点的无根树和m个操作,操作有2类:1、将节点a到节点b路径上所有点都染成颜色c;2、询问节点a到节点b路径上的颜色段数量(连续......
  • 树链剖分
    P3379【模板】最近公共祖先(LCA)本题中的树链剖分均指重链剖分。这里不使用重链剖分作为模板是因为这道题更加典型,不需要使用额外的数据结构,就是纯天然、无污染的树剖(我诗兴大发喝多了)。首先,树剖是一个思想,可以将树上两点路径的问题转变为一个序列上,不超过\(O(\logn)\)段的问......
  • 【代码仓库】【模板】树链剖分
    #include<bits/stdc++.h>#definerep(i,a,b)for(inti=(a);i<=(b);i++)#definepre(i,a,b)for(inti=(a);i>=(b);i--)#defineEde(i,u)for(inti=h[u];i;i=ne[i])#definego(i,a)for(autoi:a)//#defineintlonglong#def......
  • 【学习笔记】(18) 长链剖分
    长链剖分1.算法简介与性质长链剖分本质上就是另外一种链剖分方式。长链剖分与重链剖分有相通之处,后者是将子树大小最大的儿子作为重儿子,前者则是将子树深度最大的儿子作为重儿子。可见两者只是换了一个剖分形式。长链剖分有如下性质:性质1:每个节点所在长链末端为其子树......
  • HDU3966(树链剖分)
    题目:Aragorn'sStory 题意:给一棵树,并给定各个点权的值,然后有3种操作:IC1C2K:把C1与C2的路径上的所有点权值加上KDC1C2K:把C1与C2的路径上的所有点权值减去KQC:查询节点编号为C的权值 分析:典型的树链剖分题目,先进行剖分,然后用线段树去维护即可,注意HDU的OJ采用Windows系统,容易......