我有一棵树。我想回答如下问题:
我正在使用重光分解。树中有n
个节点和m
个查询。通过HLD,当我知道最低共同祖先时,我可以将u
和v
的任何查询分为两个不同的查询:从u
到{{1从lca
到v
。因此,该查询将在lca
时间(O(log^2n)
)回答,从log
和u
升级到v
,lca
对于重路径上的分段树。)
如您所知,HLD内置log
时间,因此总时间为O(n)
。我的问题是如何使用已建立的HLD找到LCA。我无法发明算法。
我可以使用二进制爬升来获得LCA,但需要进行O(n + m*log^2n)
预处理,这会使渐近行为变得更糟。我也可以使用范围最小查询,这不会破坏时间,但我想在此过程中使用HLD。谢谢你的任何想法!
答案 0 :(得分:1)
让我们假设我们知道如何检查一个节点是否是另一个节点的祖先(我们可以通过预先计算进入时和在深度优先遍历期间离开每个顶点时的时间来实现)。我的想法是从其中一个顶点跳起来找到lca。
让我们看一下当前路径的最顶端。如果它不是另一个的祖先,我们跳转到它,然后转到它的父级(寻找树中更高处的lca)。
否则,lca就在这条路径的某个地方。我们可以二进制搜索它(它是最低的顶点,使得它是另一个顶点的祖先)。
我们访问大多数O(log n)
路径,我们二元搜索其中一条路径。因此,此方法的总时间复杂度为每个查询O(log n)
。