LCA

概念讲解

什么是 LCA?

最近公共祖先(Lowest Common Ancestor)是树上两点最近的公共祖先。

应用

  • 求树上两点距离
  • 求树上路径
  • 树上差分

倍增法

思路

  1. 预处理每个节点的 2k2^k 级祖先
  2. 先将两点调整到同一深度
  3. 再一起向上跳

代码

123456789101112131415161718192021222324252627const int LOG = 20;
int parent[N][LOG], depth[N];

void build(int n) {
    for (int j = 1; j < LOG; j++) {
        for (int i = 1; i <= n; i++) {
            parent[i][j] = parent[parent[i][j-1]][j-1];
        }
    }
}

int lca(int u, int v) {
    if (depth[u] < depth[v]) swap(u, v);
    for (int j = LOG-1; j >= 0; j--) {
        if (depth[u] - (1 << j) >= depth[v]) {
            u = parent[u][j];
        }
    }
    if (u == v) return u;
    for (int j = LOG-1; j >= 0; j--) {
        if (parent[u][j] != parent[v][j]) {
            u = parent[u][j];
            v = parent[v][j];
        }
    }
    return parent[u][0];
}

树上距离

123int dist(int u, int v) {
    return depth[u] + depth[v] - 2 * depth[lca(u, v)];
}

考点分析

初赛考查方式

  1. 程序阅读: LCA 算法
  2. 编程题: 树上问题

常见考点

  • LCA 倍增法
  • 树上距离
  • 树上路径

例题精讲

例题 1:LCA

题目: 求树上两点的 LCA。

解答:

使用倍增法,先对齐深度再一起上跳。

练习题

  1. LCA 的作用是什么?
查看答案

LCA 的作用:

  1. 求树上两点距离:dist(u,v) = depth[u] + depth[v] - 2*depth[lca(u,v)]
  2. 求树上路径:u → LCA → v
  3. 树上差分:路径上的点权修改
  1. 倍增法的时间复杂度是多少?
查看答案
  • 预处理:O(nlog⁡n)O(n \log n)
  • 单次查询:O(log⁡n)O(\log n)
  1. 如何用 LCA 求树上距离?
查看答案
123int dist(int u, int v) {
    return depth[u] + depth[v] - 2 * depth[lca(u, v)];
}

原理:u 到 v 的距离 = u 到根的距离 + v 到根的距离 - 2 × LCA 到根的距离

易错点

⚠️ 注意:

  1. 先对齐深度
  2. 从大到小枚举
  3. 注意边界条件
  4. LCA 是树上问题的基础