树链剖分
参考资料
实现
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;
}
应用
详见 最近公共祖先。
例题
给定一棵 个结点的树,每个节点上包含一个数值,支持以下操作:
1 x y z:表示将树从 到 结点最短路径上所有节点的值都加上 。2 x y:表示求树从 到 结点最短路径上所有节点的值之和。3 x z:表示将以 为根节点的子树内所有节点值都加上 。4 x:表示求以 为根节点的子树内所有节点值之和。
给定一棵有根多叉树,请求出指定两个点直接最近的公共祖先。
一棵树上有 个节点,每个节点都有一个权值 ,支持以下操作:
CHANGE u t:把结点 的权值改为 。QMAX u v:询问从点 到点 的路径上的节点的最大权值。QSUM u v:询问从点 到点 的路径上的节点的权值和。