본문으로 건너뛰기
김신건의 로그

매개 변수 탐색 (Parametric Search)

· 수정 · 📖 약 3분 · 1,005자/단어 #algorithm #search #binary-search #optimization
parametric search, 매개 변수 탐색, 파라메트릭 서치, 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";
}
stdin
4 11
802
743
457
539
결과
200

복잡도

항목
시간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 1300K번째 수-kokoa-lab

참고

이 글의 용어 (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] 을 세 등분하여…

이 개념을 다룬 위키 페이지 (1)

💬 댓글

사이트 검색 / 명령어

검색

스크롤 = 확대/축소 · 드래그 = 이동 · 0 = 원래 크기 · ESC = 닫기