GESP8 · 树

倍增与 LCA

核心思想:任何整数都能拆成 2 的幂之和,所以"向上跳 k 层"可以用预存的 2^j 级祖先几步跳完,O(log n)。

一、互动演示:用倍增向上跳 k 层

一条链 1→2→…→8(1 是根)。输入起点和要跳的层数 k,看 k 如何被拆成 2 的幂、一跳跳一大段。

起点

二、倍增表与跳跃代码

// up[u][j] = u 的第 2^j 级祖先
up[u][0] = parent[u];                       // 2^0 = 1 级
for (int j = 1; j < LOG; j++)
  for (int u = 1; u <= n; u++)
    up[u][j] = up[ up[u][j-1] ][j-1];        // 跳 2^(j-1) 两次 = 2^j

// 把 u 向上跳 k 层:按 k 的二进制位,逐位跳
for (int j = 0; j < LOG; j++)
  if (k & (1 << j)) u = up[u][j];

求 LCA:先把深的一方跳到与浅的同深度,若已相同即答案;否则两点一起向上倍增,直到父节点相同。