长链剖分
做法
类似于轻重链剖分,只是将轻重链剖分中重儿子的定义改为,子树中深度最大的儿子
那么可以通过长链剖分来维护有关深度的信息
考虑维护节点$x$的深度信息
那么先让节点$x$继承重儿子的所有信息
再暴力合并所有轻儿子的信息
代码跟轻重链剖分差不多
void dfs(int x,int fa) { md[x]=de[x]; for (int i=0;i<(int)e[x].size();i++) { int u=e[x][i]; if (u!=fa) { de[u]=de[x]+1; dfs(u,x); if (md[son[x]]<md[u]) { son[x]=u; md[x]=md[u]; } } } }
复杂度&证明
节点x继承重儿子信息的复杂度可以做到$O(1)$
那么整个长链剖分的复杂度为$O(n)$
证明:
因为每一个节点都属于树上的一个重链上
而每个重链作为轻儿子去暴力合并只有一次,就是当在重链顶端的节点的父亲合并时,将这条重链视为轻儿子
那么每个点被枚举到1次
那么均摊复杂度为$O(n)$