문제 링크
- http://icpc.me/18932
사용 알고리즘
- Centroid Decomposition
시간복잡도
- $O((N+Q) \log^2 N)$
풀이
1번 쿼리(간선 추가 쿼리)가 모두 주어진 다음 2번 쿼리가 주어지는, 조금 더 쉬운 문제를 생각해봅시다.
이 문제는 단순히 Centroid Tree의 각 정점에서 도달할 수 있는 다른 정점까지 도달하는 거리를 저장하는 것으로 $O(Q \log^2 N)$ 해결할 수 있습니다.
간선 추가 쿼리는 Centroid Decomposition 정보(Centroid Tree)를 Small to Large로 합치면 될 것 같다는 생각을 할 수 있습니다. 구체적으로, 연결해야 하는 두 정점이 속한 Centroid Tree의 루트부터 시작해서, 큰 서브 트리 밑에 작은 서브 트리를 넣어주면 됩니다.
하지만 잘 생각해보면 이 방식을 이용해 Centroid Tree를 합쳐도 최악의 경우에는 선형 시간을 피할 수 없다는 것을 알 수 있습니다.
Centroid Tree가 너무 균형이 안 맞는 경우에는 어쩔 수 없이 Centroid Tree를 다시 구축(rebuild)해야 합니다.
Centroid Tree에서 각 정점을 루트로 하는 서브 트리마다, 그 정점을 루트로 하는 서브 트리가 마지막으로 rebuild 되었을 때의 크기 $L_v$를 저장합시다. 간선 추가 쿼리에 의해 서브 트리가 합쳐질 때, 합친 크기가 $L_v$의 2배 이상이 될 때마다 rebuild하면, 각 서브 트리의 크기는 항상 부모 서브 트리의 $3/4$ 이하가 됩니다. 그러므로 Centroid Tree의 높이를 $O(\log N)$으로 유지할 수 있습니다.
아래 코드는 구현의 편의를 위해서 서브 트리를 합칠 때 부모 서브 트리의 $3/4$ 초과일 때 rebuild하는 방식으로 구현했습니다.
전체 코드
1 |
|