문제 링크
- https://icpc.me/26618
사용 알고리즘
- 센트로이드
시간복잡도
- $O(N \log^2 N)$
풀이
간선을 반으로 쪼개서 정점을 하나씩 새로 만들어 줍시다. 어떤 정점과 거리가 $D_i$ 만큼 떨어져 있는 정점의 가중치 합을 구하는 문제입니다.
이런 문제는 보통 쿼리를 오프라인으로 받은 다음, 센트로이드 트리에서 문제를 해결할 수 있습니다. 정점 $x$가 $v$와 정확히 $d$ 만큼 떨어져 있기 위해서는, 센트로이드 트리 상에서 $v$의 조상 $p$가 $x$와 $d-dist(v, p)$ 만큼 떨어져 있으면서 원본 트리 상에서 $x - p$ 경로 위에 $v$가 없어야 합니다. 즉, 센트로이드 트리 상에서 $p$를 기준으로 봤을 때 $v$와 $x$가 서로 다른 서브 트리에 존재해야 합니다.
이런 식으로 서로 다른 서브 트리에서 오는 정점을 처리하는 것은 BOJ 13513 트리와 쿼리 4를 통해 연습할 수 있습니다.
센트로이드 트리의 각 정점에서 자신과 $d$ 만큼 떨어진 정점들의 가중치의 합을 저장하는 std::map
등을 관리하면 $O(N \log^2 N)$ 정도 시간에 문제를 해결할 수 있습니다.
전체 코드
1 |
|