定义
最近公共祖先简称 LCA(Lowest Common Ancestor)。两个节点的最近公共祖先,就是这两个点的公共祖先里面,离根最远的那个。
性质
- 如果
不为
的祖先并且
不为
的祖先,那么
分别处于
的两棵不同子树中; - 前序遍历中,
出现在所有
中元素之前,后序遍历中
则出现在所有
中元素之后; - 两点集并的最近公共祖先为两点集分别的最近公共祖先的最近公共祖先,即
; - 两点的最近公共祖先必定处在树上两点间的最短路
倍增算法
过程
倍增算法是最经典的 LCA 求法,他是朴素算法的改进算法。通过预处理
数组,游标可以快速移动,大幅减少了游标跳转次数。
表示点
的第
个祖先。
数组可以通过 dfs 预处理出来。
现在我们看看如何优化这些跳转: 在调整游标的第一阶段中,我们要将
两点跳转到同一深度。我们可以计算出
两点的深度之差,设其为
。通过将
进行二进制拆分,我们将
次游标跳转优化为「
的二进制表示所含 1 的个数」次游标跳转。 在第二阶段中,我们从最大的
开始循环尝试,一直尝试到
(包括
),如果
,则
,那么最后的 LCA 为
。
性质
倍增算法的预处理时间复杂度为
,单次查询时间复杂度为
。 另外倍增算法可以通过交换 fa 数组的两维使较小维放在前面。这样可以减少 cache miss 次数,提高程序效率。
例题
可先求出 LCA,再结合性质
进行解答。也可以直接在求 LCA 时求出结果。
参考代码
|---|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| | #include