매개 변수 탐색 (Parametric Search)
정의
매개 변수 탐색 (Parametric Search) 은 답 자체를 이분 탐색하는 기법. “조건을 만족하는 최소값 / 최대값” 문제에서, 조건 만족 여부가 단조성 (monotonicity) 을 가지면 O(log (hi - lo)) 에 최적해를 찾는다.
배열에서 값을 찾는 Binary Search 이 아니라, “k 가 가능한가?” 를 판별하는 함수 f(k) 가 단조 증가 / 감소할 때 적용.
문제 상황과 동기
최적화 문제에서 답 후보 범위가 [lo, hi] 로 정해져 있고, 답을 직접 계산하기 어렵지만 “k 가 답이 될 수 있는가?” 는 O(g(N)) 으로 판별 가능한 상황.
- naive: lo 부터 hi 까지 모두 시도. O((hi - lo) × g(N)).
- parametric search: f(k) = (k 가 가능?) 이 단조이면, k 를 이분 탐색. O(log (hi - lo) × g(N)).
예: “N 개 랜선을 K 개로 자를 수 있는 최대 길이?” → f(len) = (len 으로 K 개 이상 가능?) 는 len 이 커질수록 false. 최대 가능 len 을 이분 탐색.
핵심 통찰: “답에 대한 조건이 단조” 면 답 공간을 이분 탐색 가능.
시각화
핵심 아이디어
invariant: f(k) 는 단조 (false…false true…true 또는 true…true false…false).
초기: lo = 가능한 최소 후보, hi = 가능한 최대 후보 + 1
while lo < hi:
mid = lo + (hi - lo) / 2
if f(mid): # mid 가 조건 만족 (예: 최소값 구하기)
hi = mid # mid 는 가능, 더 작은 값도 시도
else:
lo = mid + 1
return lo # 가장 작은 가능 값
최대값 구하기는 조건 반대로:
while lo < hi:
mid = lo + (hi - lo + 1) / 2 # 올림
if f(mid):
lo = mid # mid 가능, 더 큰 값도 시도
else:
hi = mid - 1
return lo
매 단계마다 답 후보 절반 제거.
알고리즘
최소값 찾기 (f(k): k 이상이면 가능)
parametric_min(lo, hi, f):
# f(k) = (k 가 답으로 가능한가?)
# false...false true...true 형태
while lo < hi:
mid = lo + (hi - lo) / 2
if f(mid): hi = mid
else: lo = mid + 1
return lo
최대값 찾기 (f(k): k 이하면 가능)
parametric_max(lo, hi, f):
# f(k) = true...true false...false 형태
while lo < hi:
mid = lo + (hi - lo + 1) / 2 # 올림으로 무한루프 방지
if f(mid): lo = mid
else: hi = mid - 1
return lo
실수 답 (고정 반복)
parametric_real(lo, hi, f):
for _ in range(100): # 충분한 정밀도
mid = (lo + hi) / 2
if f(mid): hi = mid
else: lo = mid
return lo
구현
// 랜선 자르기: N 개를 len 으로 잘라 K 개 이상 가능한 최대 len
#include <bits/stdc++.h>
using namespace std;
int main() {
int n, k;
cin >> n >> k;
vector<long long> a(n);
for (auto& v : a) cin >> v;
long long lo = 1, hi = *max_element(a.begin(), a.end()) + 1;
auto f = [&](long long len) {
long long cnt = 0;
for (auto x : a) cnt += x / len;
return cnt >= k;
};
while (lo < hi) {
long long mid = lo + (hi - lo + 1) / 2; // 올림
if (f(mid)) lo = mid;
else hi = mid - 1;
}
cout << lo << "\n";
}4 11
802
743
457
539200복잡도
| 항목 | 값 |
|---|---|
| 시간 | O(log (hi - lo) × T_f), T_f = f(k) 계산 시간 |
| 공간 | O(1) + f(k) 추가 공간 |
| 전제 | f(k) 가 단조 (증가 또는 감소) |
| 비교 횟수 | 약 ⌈log₂(hi - lo)⌉ |
hi - lo = 10^9 이어도 약 30 회 f(k) 호출로 끝.
변형 / 활용
| 형태 | 설명 |
|---|---|
| 랜선 자르기 | len 으로 K 개 이상 가능? (최대 len) |
| 공유기 설치 | dist 간격으로 C 개 배치 가능? (최대 dist) |
| 나무 자르기 | 높이 h 로 잘라 M 이상 가능? (최대 h) |
| 예산 배정 | 상한 b 로 총합 ≤ M? (최대 b) |
| 이분 매칭 최대 유량 | flow f 로 매칭 가능? |
| 실수 방정식 | f(x) = 0 인 x (삼분 탐색과 결합) |
함정
1. 단조성 검증 누락
f(k) 가 단조가 아니면 틀린 답. 예: “합이 정확히 K” 는 단조가 아님 (K-1, K, K+1 모두 false 가능).
2. lo, hi 초기값 실수
lo 는 가능한 최소값 이하, hi 는 가능한 최대값 초과 로 잡아야 안전.
// 잘못: hi = max(a) -> 답이 max(a) 일 때 누락
// 올바름: hi = max(a) + 1
3. mid 계산 올림 / 내림
최대값 찾기는 mid = (lo + hi + 1) / 2 (올림), 아니면 무한 루프.
// 잘못: lo = 3, hi = 4 -> mid = 3 -> lo = 3 (무한)
// 올바름: mid = (3 + 4 + 1) / 2 = 4
4. f(k) 오버플로우
k 를 long long 으로, 중간 계산도 주의.
// 잘못: int cnt = (int)x / len; cnt += ...
// 올바름: long long cnt = 0; cnt += x / len;
실전 패턴
| 문제 유형 | f(k) 의미 | 목표 |
|---|---|---|
| 최소 최대화 (minimize maximum) | k 이하로 가능? | 가장 작은 가능 k |
| 최대 최소화 (maximize minimum) | k 이상으로 가능? | 가장 큰 가능 k |
| 이분 답 (binary answer) | k 가 답? | 첫 true 또는 마지막 false |
BOJ 연습 문제
| 번호 | 제목 | 정답률 | 링크 |
|---|---|---|---|
| BOJ 1654 | 랜선 자르기 | - | kokoa-lab |
| BOJ 2110 | 공유기 설치 | - | kokoa-lab |
| BOJ 2805 | 나무 자르기 | - | kokoa-lab |
| BOJ 2792 | 보석 상자 | - | kokoa-lab |
| BOJ 1300 | K번째 수 | - | kokoa-lab |
참고
- Binary Search
- Ternary Search
- Aliens Trick (lambda 에 대한 parametric search)
이 글의 용어 (3개)
- 이분 탐색 (Binary Search)algorithm
- 정의 이분 탐색 (Binary Search) 은 정렬된 시퀀스에서 목표값의 위치를 O(log N) 에 찾는 알고리즘. 매 단계에서 후보 구간을 절반으로 줄인다. 탐색이 본질이 아…
- Aliens Trickalgorithm
- 정의 Aliens Trick (또는 WQS Binary Search, Lagrange Optimization) 은 "정확히 K 개 선택" 같은 까다로운 제약을 가진 DP 를, 제…
- Golden-section Search: 단봉 함수 최적화algorithm
- 정의 단봉 (unimodal) 함수 위에서 최소/최대를 찾는 탐색. 이분 탐색을 단봉 함수용으로 확장. 삼분 탐색 (Ternary Search) 구간 [l, r] 을 세 등분하여…
💬 댓글