树链剖分
参考资料
简介
树链剖分(Heavy-Light Decomposition,HLD)把每个非叶节点子树最大的儿子定为 重儿子,连向重儿子的边为重边,重边相连成 重链。两遍 DFS 后,每条重链的 DFS 序连续,且任意树上路径至多经过 条重链。于是树上路径与子树的修改、查询都能转化为 段连续区间,配合线段树解决。
实现
vector<int> G[N];
int fa[N],son[N],siz[N],dep[N];
int top[N],dfn[N],rnk[N],out[N];
int cnt=0;
void dfs1(int u)
{
siz[u]=1;
dep[u]=dep[fa[u]]+1;
for(auto v:G[u])
{
if(v==fa[u])continue;
fa[v]=u;
dfs1(v);
siz[u]+=siz[v];
if(siz[v]>siz[son[u]])son[u]=v;
}
}
void dfs2(int u,int t)
{
top[u]=t;
dfn[u]=++cnt;
rnk[cnt]=u;
if(son[u])dfs2(son[u],t);
for(auto v:G[u])
{
if(v==fa[u]||v==son[u])continue;
dfs2(v,v);
}
out[u]=cnt;
}
应用
详见 最近公共祖先。