Skip to main content

树链剖分

参考资料

实现

447 Bcpp
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;
}

应用

详见 最近公共祖先

例题

给定一棵 nn 个结点的树,每个节点上包含一个数值,支持以下操作:

  • 1 x y z:表示将树从 xxyy 结点最短路径上所有节点的值都加上 zz
  • 2 x y:表示求树从 xxyy 结点最短路径上所有节点的值之和。
  • 3 x z:表示将以 xx 为根节点的子树内所有节点值都加上 zz
  • 4 x:表示求以 xx 为根节点的子树内所有节点值之和。

给定一棵 nn 个点的有根树。

qq 次询问,第 ii 次询问给定 xi,kix_i, k_i,要求点 xix_ikik_i 级祖先,答案为 ansians_i。特别地,ans0=0ans_0 = 0

给定一棵有根多叉树,请求出指定两个点直接最近的公共祖先。

一棵树上有 nn 个节点,每个节点都有一个权值 wiw_i,支持以下操作:

  • CHANGE u t:把结点 uu 的权值改为 tt
  • QMAX u v:询问从点 uu 到点 vv 的路径上的节点的最大权值。
  • QSUM u v:询问从点 uu 到点 vv 的路径上的节点的权值和。