Pattern Reference
Binary Lifting
"Jump pointers for ancestors, LCA, path queries in O(log n)."
Loading...
Deep Dive Tutorial
Binary lifting precomputes up[v][k] = 2^k-th ancestor of v. Build: up[v][0]=parent[v]; for k≥1: up[v][k]=up[up[v][k-1]][k-1]. O(n log n) build, O(log n) query. LCA: equalize depths by lifting the deeper node, then lift both simultaneously until they meet. Extension: store min/max/sum along the path in the lifting table — O(log n) path aggregate queries.
Binary lifting for LCA and kth ancestor
const LOG = 18; // log2(10^5) ≈ 17
function buildBinaryLifting(n, parent, root = 0) {
const up = Array.from({length: n}, () => new Array(LOG).fill(-1));
const depth = new Array(n).fill(0);
// BFS to set parent and depth
const queue = [root];
const visited = new Array(n).fill(false);
visited[root] = true;
while (queue.length) {
const v = queue.shift();
up[v][0] = parent[v] ?? -1;
for (let k = 1; k < LOG; k++) {
if (up[v][k-1] !== -1) up[v][k] = up[up[v][k-1]][k-1];
}
for (const u of (adj[v] || [])) {
if (!visited[u]) {
visited[u] = true;
depth[u] = depth[v] + 1;
parent[u] = v;
queue.push(u);
}
}
}
return { up, depth };
}
function kthAncestor(v, k, up) {
for (let i = 0; i < LOG; i++) {
if ((k >> i) & 1) {
v = up[v][i];
if (v === -1) return -1;
}
}
return v;
}
function lca(u, v, up, depth) {
if (depth[u] < depth[v]) [u, v] = [v, u];
// Bring u to same depth as v
u = kthAncestor(u, depth[u] - depth[v], up);
if (u === v) return u;
// Binary lift both until they diverge
for (let k = LOG - 1; k >= 0; k--) {
if (up[u][k] !== up[v][k]) {
u = up[u][k];
v = up[v][k];
}
}
return up[u][0];
}Worked Problems
move-up
Binary lifting complexity: O(n log n) preprocess, O(log n) per query. LOG = ceil(log2(n)) — use 18 for n ≤ 10^5, 20 for n ≤ 10^6.
LCA applications:
- Path sum from u to v: sum[u] + sum[v] - 2*sum[LCA]
- Distance: depth[u] + depth[v] - 2*depth[LCA]
- Path min/max: extend lifting table to store edge weights
Euler tour + sparse table: Alternative for static trees — O(n) preprocess, O(1) LCA query. Better for offline many-query scenarios.
LCA applications:
- Path sum from u to v: sum[u] + sum[v] - 2*sum[LCA]
- Distance: depth[u] + depth[v] - 2*depth[LCA]
- Path min/max: extend lifting table to store edge weights
Euler tour + sparse table: Alternative for static trees — O(n) preprocess, O(1) LCA query. Better for offline many-query scenarios.