树上一点,满足删除该点时,树内剩下的子树最大节点数最小。
1、树的重心每棵子树的大小一定小于等于\(n/2\)
2、每颗子树的大小都小于等于\(n/2\)的点一定是这棵树的重心(就是上一个的逆定理)
3、树中所有点到某个点的距离和中,到重心的距离和最小(如果有两个重心,他们的距离一样)
证明:我们考虑使用调整法,设当前最优决策为u点,v为u的任意相邻节点。记size(x)为当u为整棵树的根时,以x为根的子树的节点的大小。
u为全局最优决策当且仅当\(n-size(v)\ge size(v)\),否则最优策略一定在不满足该条件的v的子树中。
我们化简这个式子,即\(size(v)\le n/2\)
由定理2得,该点为树的重心。
4、两棵树通过一条边相连成为一颗新的树,新树重心一定在原来两棵树得重心的路径上。(注意中心不止一个的情况)
例题:cf civilization
方法1:处理出每个节点的????,依次枚举点,模拟删除该点后各子树大小,更新最优解。
方法2:采用“调整法”的思想,从一个点出发,调整过去。
两种方法都是Ο(?)的。
树(可带权)上最长的简单路径。
1、一棵树的直径可能有若干条,但是有一点显然――他们一定两两相交,不然我们就一定可以找出一条更长的。
2、所有直径的交集一定非空。因为如果三条直径两两相交。如果他们没有共同交集,那么就会形成环。然后我们可以一直推广到所有直径的情况。
3、以树上任意一个点作为起点的最长路径,重点一定是直径上的一个端点。
在此捞上栋栋小哥哥的证明:

4、对于两条相交直径,他们不相交的部分一定对称。
5、两棵树用一条边合并,新树的直径两端一定是原本两棵树直径四个端点中的两个。
证明:(1)直径不经过新边 这个时候显然是原本两条直径中的一条。否则就不满足直径的定义了。(2)直径经过新边。 新边两端分属两棵树,那么这条直径的新边的两端部分肯定是从这两个点出发在各自树中的最长路径。根据性质3,端点还是四个端点的其中之二。
由于性质3,我们可以通过两次bfs或者dfs来确定直径――任选一点,通过搜索找到从该点出发的最长路,由性质得到,终点为直径的一个端点。从该端点出发,再通过搜索找到最长路,由定理得,此终点一定是直径的另外一个端点。
事实上是懒得学了??)
从根节点开始dfs遍历树――在点x时,走到一个未遍历过的儿子,或者儿子已经全部遍历过从x返回到父亲时,以此法得到的遍历序列是欧拉序。
从根节点开始dfs遍历树,一个节点第一次被遍历到时加入到序列中,以此法得到的遍历序列是dfs序。
从根节点开始dfs遍历树,一个节点第一次被遍历或者遍历完儿子要退出时将其加入到序列中,以此法得到的遍历序列是括号序。
1、将树中子树表示为遍历序列的一段区间。(括号序)
2、判断一个点是否在以另外一个点为根的子树里。
(设一个点x在dfs序列中位置为dfn(x),那么如果点y在以x为根的子树离=>\(dfn(x)\le dfn(y)<dfn(x)+size(x)\)
3、和2等价的,还可以推出判断点x是否在点y到根节点的路径上(只要判断不在子树里就可以了)
4、再考虑这样的一类询问,求点x到根路径上所有点的权值和,且存在修改点权操作。
显然,每个点的权值,对以该点为根的子树的所有点都有贡献,所以每次修改操作(初始化时给点赋值也看成修改)就可以将以该点为根的子树所有点答案加上修改的值。
处理时我们可以开一颗全局线段树,每个点在其中的下标就是该点的dfs序,值为该点的权值。
求答案时就是单点查询该点在线段树中的权值,修改时就是对整棵子树进行区间修改。
但是还有更简单的方法!我们考虑括号序列。
我们开一个大小为2n的数组,点x在位置\(arr_x\)插入权值,从位置\(lea_x\)插入权值的相反数,做一次前缀和后,设\(sum_i\)为前i项的和,显然点x到根节点的路径权值就是\(sum_{arr_x}\)
维护这个可以修改的前缀和数组可以用树状数组qwq
1.????(?)为节点?为根的子树的节点大小。
2.令?是?的儿子中????(?)最大的儿子(如果有多个,则任选一个),则称边(?,?)为重边,?为?的重儿子。
3.重路径:一条路径为重路径,当且仅当这条路径全由重边组成。
4.轻边:令?是?的儿子(?≠?),那么称边(?,?)为轻边(即使????(?)=????(?)),?为?的轻儿子。
第一步,dfs出每个点的size。
第二步,找出每个点的重边,给点重新编号(DFS序),并将重边连为重链。
第三步,建立一个以新编号为下标的数据结构(一般都是线段树吧),维护树上的信息。
啊。。。。其他的东西去参考专门的博文吧qwq,我这里又不是讲树链剖分的。我的初衷是整理给自己看的
单点修改和查询\(O(log(n))\),路径修改和查询为\(O(log(n)^2)\)
1、如果v是u的儿子,且\((u,v)\)是一条轻边,那么\(size(v)<\frac{size(u)}{2}\)
则有
由定理8,如果经过了一条轻边,当前子树点的个数至多变为原来的一半。最初子树的点为?,?的子树的点的个数至少为1,所以至多经过logn条轻边。
由这个引理,我们也可以得知,每个点到根的路径上的轻边和重路径条数都不超过logn。
dsu on tree
本质是树上启发式合并,可以解决多数无修改的子树查询问题。
例如:每个点有一个颜色,询问每个子树中颜色种类数。
首先,对每个点求出重儿子和轻儿子,维护一个颜色为下标的桶,开始dfs,假设当前到点x我们先将x的轻儿子都递归,每次退出递归时把桶都清空。
最后在递归x的重儿子,返回时无需清空。 然后再将除重儿子的部分加进来,即可得到x子树的桶。
考虑一个点暴力加入和暴力清空的次数,显然和它到轻边的数量有关,那么一个点只会有log次。
选择最深的子树进行剖分。
与重链剖分类似,对于树高最高的儿子子树,称为长儿子,多个仍选择一个,其余都是短儿子。
经典应用是求K级祖先和一些和树上的深度有关的题目;
博客参考:zzq dalao的博客 戳我
LCT