algorithmtreelowest-common-ancestor

How to find LCA using HLD?


I have a tree. I want to answer queries such as:

  1. Add value on a path
  2. Get sum on a path

I am using Heavy-Light Decomposition. There are n nodes in the tree and m queries. With HLD, when I know the Lowest Common Ancestor, I can separate any query for u and v into two distinct ones: from u to lca and from v to lca. As a result, the query will be answered in O(log^2n) time (log to go up from u and v to lca, and log for segment trees on heavy paths).

As you know, HLD is built in O(n) time, as a result, total time is O(n + m*log^2n). My question is how to find LCA using already built HLD. I cannot invent the algorithm.

I can use binary climb to get LCA, but it takes O(nlogn) preprocessing, which will make asymptotic behaviour worse. I can also use Range Minimum Query, which doesn't spoil the time, but I'd like to use HLD for this procedure. Thank you for any ideas!


Solution

  • Let's assume that we know how to check if one node is an ancestor of the other one (we can do it by precomputing the time when we enter and when we leave each vertex during the depth-first traversal). The idea is to jump up from one of the vertices to find the lca.

    1. Let's look at the topmost vertex of the current path. If it's not an ancestor of the other one, we jump to it and then go to its parent (to look for the lca somewhere higher in the tree).

    2. Otherwise, the lca is somewhere on this path. We can binary search for it (it's the lowest vertex such that it's an ancestor of the other one).

    We visit at most O(log n) paths and we binary search over one of them. So the total time complexity of this approach is O(log n) per query.