“树上的最近公共祖先是倍增的招牌应用:先把较深点提到同一深度;若两点已经相同,立即返回该点。否则从高位到低位,只在两点的 $2^k$ 级祖先不同时让它们同时跳过去,最后返回任一点的父亲。每次跳…”
形式陈述
接口与参数约定
给定含
等价的第
树的唯一根路径保证答案存在且唯一。若
Binary Lifting 基线
二进制倍增保存
预处理与空间为
先把查询压成一次跳跃与一次索引
先求每个节点到最深后代的边数
节点
若每个节点都保存全部跳指针,这个办法的查询已经是
用宏节点和微树把跳指针压到线性
以下在字长
仅对跳节点保存全部有效二次幂祖先;距离超过其深度时使用无祖先哨兵。构建时不需要先给所有其他节点建倍增表:知道距离
所有跳节点及其祖先称为宏节点,组成一棵连通宏树。一次遍历给每个宏节点
删除宏节点后的每个连通分量是少于
时间和字空间。每棵实际微树只保存形状编码、根深度,以及本地编号到实际节点的数组,总共
查询若仍在原微树内,就查该形状表并还原节点;目标在微树之外时,直接转到微树根的父节点,再使用宏节点算法。最高置位也可由长度
微树形状表、跳节点表和 ladder 各有单独的线性预算;它们共同支撑这个静态界。
直觉
倍增把向上距离拆成二进制跳跃,ladder 方案则先用最高位跳到一条足够长的祖先链,再按深度直接索引剩余距离。后者利用长路径分解与有限复制把所有梯子总长控制在线性范围,从而以更细预处理换掉查询中的对数次跳转。
图右侧是原路径
例子与边界
可追踪真例
设根路径为
第 ancestor(y,3) 与
推论与应用
与 LCA、动态树的区分
最近公共祖先输入两个节点并寻找最深公共祖先;Level Ancestor 输入一个节点和一个深度。LCA 算法可以调用祖先跳跃作为子程序,Level Ancestor 也能帮助对齐深度,但两个问题的接口和最优预处理并不相同。
若树发生 link、cut 或换根,深度和 ladder 可能整体改变,静态线性预处理立即失效。动态版本应进入动态森林问题并分别报告更新、查询及换根成本,不能沿用本页
简洁树表示还可用平衡括号与 rank/select 支持祖先导航;其重点是 bit 空间,而非把指针树的
参考资料
- Michael A. Bender and Martín Farach-Colton, “The Level Ancestor Problem Simplified”, LATIN 2002 版本,§3.3–3.4 与 §4:ladder、跳节点及宏微树证明;期刊版发表于 Theoretical Computer Science 321(1), 2004。
- Omer Berkman and Uzi Vishkin, “Finding Level-Ancestors in Trees,” Journal of Computer and System Sciences 48(2), 1994.
- Paul F. Dietz, “Finding Level-Ancestors in Dynamic Trees,” WADS, 1991, for the dynamic contrast.