무엇을 해결하나
머지 소트 트리는 "구간 \([l, r]\) 안에서 값이 \(k\)보다 큰(작은) 원소의 개수",
나아가 "구간 \([l, r]\)의 \(j\)번째로 작은 수" 같은 질의를 처리하는 정적 자료
구조다. 배열은 갱신되지 않는다고 가정한다.
핵심 발상은 표준 세그먼트 트리의 각 노드에, 그 노드가 담당하는 구간의 원소들을
정렬한 배열을 통째로 저장하는 것이다. 노드의 정렬 배열은 두 자식의 정렬
배열을 병합(merge)해 만든다 — 그래서 이름이 "머지 소트 트리"다.
[1,2,3,5,7,8] (전체)
/ \
[2,5,7] [1,3,8]
/ \ / \
[5,2] [7] [3,1] [8]
메모리와 구축
깊이마다 모든 원소가 정확히 한 번씩 나타나므로 한 깊이의 총 크기는 \(N\)이고,
깊이가 \(O(\log N)\)이라 전체 메모리는 \(O(N \log N)\)이다. 각 노드 배열을 자식
병합으로 만들면 구축 시간도 \(O(N \log N)\) — 사실상 병합 정렬과 같다.
질의: "k보다 큰 원소 개수"
구간 질의 \([l, r]\)은 표준 세그 트리처럼 \(O(\log N)\)개의 노드로 분해된다. 각
노드는 정렬 배열을 들고 있으므로, 이분 탐색으로 그 안에서 \(k\) 초과 원소
개수를 \(O(\log N)\)에 센다. 분해된 노드가 \(O(\log N)\)개이므로 한 질의는
\(O(\log^2 N)\)이다.
핵심: "구간을 노드로 쪼개기" \(O(\log N)\) × "노드 안 이분 탐색" \(O(\log N)\)
\(= O(\log^2 N)\).
질의: "구간 k번째 수"
값에 대해 한 번 더 이분 탐색을 씌운다. "값 \(x\) 이하가 구간 안에 몇 개인가"를
위 방법으로 세면서, 그 개수가 \(k\) 이상이 되는 최소 \(x\)를 찾는다. 그러면 한
질의가 \(O(\log^3 N)\)이 되는데, 값을 좌표 압축하고 외부 이분 탐색을 세그 트리
내부 하강과 합치는 분수 캐스케이딩 기법으로 \(O(\log^2 N)\)까지 줄일 수
있다(고급).
다른 풀이와의 비교
구간 k번째 수는 퍼시스턴트 세그먼트 트리로 \(O(\log N)\)에, 오프라인 + Mo's
알고리즘으로도 풀 수 있다. 머지 소트 트리는 구현이 단순하고 "초과/이하 개수"
같은 부등식 카운팅에 특히 직관적이라는 강점이 있다.