문제
2차원 격자에서 점 갱신과 직사각형 질의(합/최대/최소)를 빠르게 처리한다. 1차원 세그먼트 트리가 \(O(\log n)\) 이듯, 2차원에서는 두 축 모두에 세그먼트 트리를 세워 \(O(\log^2)\) 을 노린다.
트리의 트리 구조
바깥 트리는 \(x\)축을 구간 분할한다. 바깥 트리의 각 노드는 그 \(x\) 구간에 속한 점들로 만든 안쪽 \(y\)축 세그먼트 트리를 가진다. 직사각형 \([x_1,x_2]\times[y_1,y_2]\) 질의는:
- 바깥 트리에서 \([x_1,x_2]\) 를 덮는 \(O(\log n)\) 개 노드를 고른다.
- 각 노드의 안쪽 트리에서 \([y_1,y_2]\) 합을 \(O(\log m)\) 에 구한다.
총 \(O(\log n\log m)\).
점 갱신
점 \((x,y)\) 를 갱신하면 바깥 트리에서 \(x\) 를 포함하는 루트→리프 경로의 \(O(\log n)\) 개 노드 각각에서, 그 안쪽 트리의 \(y\) 위치를 \(O(\log m)\) 에 갱신한다. 총 \(O(\log n\log m)\).
메모리: 빽빽함 vs 동적
격자가 \(N\times M\) 으로 작으면 안쪽 트리를 배열로 통째 잡아 \(O(NM)\) 메모리. 좌표가 크고 점이 희소하면:
- 동적(포인터) 안쪽 트리: 안쪽 노드를 필요할 때만 생성. 점 \(Q\) 개면 메모리 \(O(Q\log n\log m)\).
- 좌표 압축 + 머지소트 트리: 정적 질의면 각 바깥 노드에 정렬된 \(y\) 리스트를 두는 변형도 있다.
다른 접근과 비교
| 방법 | 갱신 | 질의 | 비고 |
|---|---|---|---|
| 2D BIT | \(O(\log n\log m)\) | \(O(\log n\log m)\) | 합 전용, 구현 짧음 |
| 2D 세그트리 | \(O(\log n\log m)\) | \(O(\log n\log m)\) | min/max 등 일반 결합 |
| 오프라인 + 정렬 + 1D BIT | \(O(\log)\) | — | 점 갱신·정적이면 가장 빠름 |
합만 필요하면 2D 펜윅이 더 짧다. min/max처럼 역원이 없는 결합이나 구간 갱신이 필요하면 2D 세그먼트 트리가 답이다.
주의
2D 세그트리에서 구간(직사각형) 갱신 + 직사각형 질의 를 동시에 lazy로 지원하는 것은 매우 까다롭다. 일반적으로 점 갱신/직사각형 질의 또는 직사각형 갱신/점 질의 중 하나로 설계한다.