分尸(树)

重链剖分

思路

考虑将一个节点的儿子中所在子树最大的一个儿子作为重儿子,相连的边为重边,每次延重儿子划分划出来的链我们称之为重链。

对于一条链如果往上跳,必然是个轻边,所以必然存在一个重儿子的字数大于当前链所在子树,所以没往上条链,子树大小至少为原来两倍,所以时间复杂度为 \(logn\)

code

void DFS(int x, int fa) {
  sz[x] = 1;
  for (int i : g[x]) {
    if (i == fa) continue;
    dep[i] = dep[x] + 1, DFS(i, x), sz[x] += sz[i], gfa[i] = x, (sz[son[x]] < sz[i]) && (son[x] = i);
  }
}

void S(int x, int fa, int to) {
  top[x] = to, dfn[x] = ++cnt, mxdfn[x] = dfn[x];
  if (son[x]) S(son[x], x, to), mxdfn[x] = max(mxdfn[x], mxdfn[son[x]]);
  for (int i : g[x]) {
    if (i == fa || i == son[x]) continue;
    S(i, x, i), mxdfn[x] = max(mxdfn[i], mxdfn[x]);
  }
}

长链剖分

posted @ 2024-08-21 21:33  yabnto  阅读(8)  评论(0编辑  收藏  举报