직선 집합 위의 최솟값 질의
여러 직선 \(f_k(x)=a_k\ x + b_k\) 가 있을 때 임의의 \(x\) 에서 \(\min_k f_k(x)\) (또는 \(\max\))를 구하는 문제는 DP 최적화의 단골이다. 예를 들어
$$ dp[i] = \min_j\big(dp[j] + a_j\cdot x_i + b_j\big) $$
처럼 전이가 "직선의 점 평가"로 쓰이는 경우다. 기울기와 질의가 모두 단조라면 단순 Convex Hull Trick(스택)으로 \(O(1)\) 균등 처리가 가능하지만, 임의 순서로 직선이 추가되고 임의의 \(x\) 가 질의 되면 정렬 가정이 깨진다. Li Chao 트리가 이 동적 상황을 처리한다.
핵심 아이디어
\(x\) 의 정의역 \([L,R]\) 위에 세그먼트 트리를 세운다. 각 노드는 "그 구간에서 가장 자주 최소가 되는 직선" 하나를 들고 있다. 새 직선 \(g\) 를 노드 구간 \([l,r]\) 에 삽입할 때:
- 중점 \(m=(l+r)/2\) 에서 기존 직선 \(f\) 와 \(g\) 를 비교, 중점에서 더 낮은 쪽을 노드에 남긴다.
- 끝점 \(l\) 에서의 우열을 보고, 노드에 진 쪽을 한쪽 자식으로 내려보낸다. 두 직선은 한 번만 교차하므로(선형) 한쪽 절반에서만 역전될 수 있다.
이렇게 하면 각 노드에는 항상 그 구간 중점에서 우세한 직선이 남고, 패배한 직선은 자신이 우세할 수 있는 절반으로만 내려간다.
정확성 스케치
두 직선은 많아야 한 점에서 교차한다. 노드 구간을 중점 기준 두 절반으로 나누면, 진 직선이 다시 우세해질 수 있는 곳은 둘 중 한 절반에 통째로 들어간다. 따라서 진 직선을 그 절반의 자식으로 내려보내면 손실이 없다. 깊이 \(O(\log V)\) (\(V\) = 좌표 범위)마다 \(O(1)\) 비교이므로 삽입/질의 모두 \(O(\log V)\).
질의
점 \(x\) 질의는 루트→리프 경로의 모든 노드 직선을 평가해 최솟값을 취한다. 경로 길이가 \(O(\log V)\).
CHT 비교표
| 방법 | 직선 추가 | 질의 | 제약 |
|---|---|---|---|
| 단조 CHT(스택) | 기울기 정렬 시 amort. \(O(1)\) | 질의 단조 시 \(O(1)\) | 둘 다 단조 필요 |
| Li Chao 트리 | \(O(\log V)\) | \(O(\log V)\) | 제약 없음 |
| Kinetic/세그트리 빔서치 | \(O(\log^2 V)\) | \(O(\log V)\) | 구간 삽입 가능 |
좌표가 실수이거나 매우 크면 좌표 압축 또는 동적(포인터) 노드 할당으로 정의역을 다룬다.