-
LCA를 필요로 하는 문제들 중 많은 수는 경로 쿼리를 처리하기 위함이다. 두 노드 u,v 간의 경로 u→v 에 대한 쿼리를 처리할때, 경로를 u → lca, lca → v 로 나누어 각각에 대한 쿼리를 처리한 뒤 합치는 방식으로 사용된다.
그러면 이제 lca를 구한 다음에, u→lca 까지의 경로와, lca→v 까지의 경로에 대해서 뭔가를 계산해줘야 하는 경우들이 많은데. 이게 역연산이 가능한 경우라면 (대표적으로는 구간들의 합으로 계산되는 거리 구하기 문제), f(u,lca) = f(root,u)- f(root,lca) 와 같은식으로 누적합 비슷한 방법으로 처리가 가능하지만, 복잡한 쿼리들은 경로를 구간들로 쪼개서 뭔가를 해줘야 한다.
그래서 LCA를 구할때도, LCA 자체를 빨리 구하는 것을 넘어서, LCA를 구하고 이러한 구간처리까지 함께 효율적으로 해줄수 있는 방법을 사용하는 것이 좋다.
두 노드에서 리프팅해서 LCA까지 찾아가는 방법들은, 그렇게 올라간 과정이 경로로 남게 되므로 이 목적에 적합하다.
업데이트가 없는 경로 쿼리를 처리해야 한다면, 바이너리 점핑 테이블을 쓰면 된다. 전처리 O(nlogn), LCA쿼리 O(logn), 경로쿼리 O(logn)이다. 바이너리 점핑 테이블을 만들어두면 k번째 조상 찾기와 같은 쿼리도 O(logn)에 처리할수 있다
업데이트가 있는 경로 쿼리라면, HLD가 필요하다. HLD로 쪼갠 구간들을 segment tree 로 관리한다 치면 경로 쿼리에 O(log^2n)이 걸린다. 전처리는 O(n), LCA쿼리는 O(logn), 경로쿼리 O(log^2n)이다