추천 문제 - 파라메트릭 서치
[BOJ] LJUBOMORA (소스코드) - [low, high) 조건 내 이분 탐색, 최소 조건 찾기(high
)
[BOJ] 랜선 자르기 (소스코드) - [low, high) 조건 내 이분 탐색, 최대 조건 찾기(low
)
[BOJ] 히오스 프로게이머 (소스코드) - [low, high) 조건 내 이분 탐색, 최대 조건 찾기(low
) (조건문 주의할 것)
[BOJ] 공유기 설치 (소스코드) - [low, high) 조건 내 이분 탐색, 최대 조건 찾기(low
)
[BOJ] 휴게소 세우기 (소스코드) - [low, high) 조건 내 이분 탐색, 최대의 최소 조건 찾기(high
)
[BOJ] 숫자 구슬 (소스코드) - [low, high) 조건 내 이분 탐색, 최대의 최소 조건 찾기(high
) + 문제의 조건에 따라 cnt
를 잘 갱신해야 함
[BOJ] 흩날리는 시험지 속에서 내 평점이 느껴진거야 (소스코드) - [low, high) 조건 내 이분 탐색, 최소의 최대 조건 찾기(low
) + 문제의 조건에 따라 cnt
를 잘 갱신해야 함
[BOJ] 공정 컨설턴트 호석 (소스코드) - [low, high) 조건 내 이분 탐색, 최소 조건 찾기(high
) + priority_queue
정렬되어 있는 배열에서 특정 요소를 찾기 위해 모든 데이터를 순차적으로 탐색하는 것(선형탐색)이 아닌 탐색 범위를 절반으로 줄여가며 탐색하는 방법(이분탐색)
선형탐색의 시간복잡도는 O(n )
이분탐색의 시간복잡도는 O(log n )
#include <string.h>
#include "key.h"
/* binsearch: find word in tab[0]...tab[n-1] */
struct key * binsearch (char * word , struct key tab [], int n )
{
int cond ;
struct key * low = & tab [0 ];
struct key * high = & tab [n ];
struct key * mid ;
while (low < high ) {
mid = low + (high - low ) / 2 ; /* `mid = (low + high) / 2` is WRONG! */
if ((cond = strcmp (word , mid -> word )) < 0 )
high = mid ;
else if (cond > 0 )
low = mid + 1 ;
else
return mid ;
}
return NULL ;
}
#include < iostream>
#include < vector>
#include < algorithm>
int main () {
int n;
std::cin >> n;
std::vector<int > v (n);
for (int i = 0 ; i < n; ++i)
std::cin >> v[i];
std::sort (v.begin (), v.end ());
int m;
std::cin >> m;
while (m--) {
int target;
std::cin >> target;
auto low = v.begin ();
auto high = v.end ();
while (low < high) {
auto mid = low + (high - low) / 2 ;
if (target < *mid)
high = mid;
else if (target > *mid)
low = mid + 1 ;
else
break ;
}
std::cout << ((low < high) ? 1 : 0 ) << ' \n ' ;
}
return 0 ;
}
#include < iostream>
#include < vector>
#include < algorithm>
int main () {
int n;
std::cin >> n;
std::vector<int > v (n);
for (int i = 0 ; i < n; ++i)
std::cin >> v[i];
std::sort (v.begin (), v.end ());
int m;
std::cin >> m;
while (m--) {
int target;
std::cin >> target;
std::cout << binary_search (v.begin (), v.end (), target) << ' \n ' ;
}
return 0 ;
}
Returns an iterator pointing to the first element which does not compare less than val .
template <class ForwardIterator , class T >
ForwardIterator lower_bound (ForwardIterator first,
ForwardIterator last,
const T& val)
{
ForwardIterator it;
iterator_traits<ForwardIterator>::difference_type count, step;
count=distance (first,last);
while (count>0 ) {
it=first;
step=count/2 ;
advance (it,step);
if (*it<val) {
first=++it;
count-=step+1 ;
}
else {
count=step;
}
}
return first;
}
Returns an iterator pointing to the first element which compares greater than val .
template <class ForwardIterator , class T >
ForwardIterator lower_bound (ForwardIterator first,
ForwardIterator last,
const T& val)
{
ForwardIterator it;
iterator_traits<ForwardIterator>::difference_type count, step;
count=distance (first,last);
while (count>0 ) {
it=first;
step=count/2 ;
advance (it,step);
if (!(val<*it)) {
first=++it;
count-=step+1 ;
}
else {
count=step;
}
}
return first;
}
lower_bound
, upper_bound
예시
#include < algorithm>
#include < iostream>
#include < iterator>
#include < vector>
int main () {
std::vector<int > data = {1 , 1 , 2 , 3 , 3 , 3 , 3 , 4 , 4 , 4 , 5 , 5 , 6 };
auto lower = std::lower_bound (data.begin (), data.end (), 4 );
auto upper = std::upper_bound (data.begin (), data.end (), 5 );
// result: 4 4 4 5 5
// idx : 0 1 2 3 4 5 6 7 8 9 10 11 12
// data: 1 1 2 3 3 3 3 4 4 4 5 5 6
// lower_bound: the lower will indicate to the idx 7
// the first element which does not compare less than 4
// upper_bound: the upper will indicate to the idx 12
// the first element which compares greater than 5
std::copy (lower, upper, std::ostream_iterator<int >(std::cout, " " ));
return 0 ;
}
#include < iostream>
#include < vector>
#include < algorithm>
int main () {
int n;
std::cin >> n;
std::vector<int > v (n);
for (int i = 0 ; i < n; ++i)
std::cin >> v[i];
std::sort (v.begin (), v.end ());
int m;
std::cin >> m;
while (m--) {
int t;
std::cin >> t;
auto upper = std::upper_bound (v.begin (), v.end (), t);
auto lower = std::lower_bound (v.begin (), v.end (), t);
std::cout << upper - lower << ' ' ;
}
return 0 ;
}
이분 탐색 응용
최적화 문제, 이를테면 주어진 조건을 만족하는 값 중에서 최소 혹은 최대값을 구하는 문제를 결정 문제 로 바꾸어 푸는 것
이분 탐색을 사용해 탐색 범위를 줄여놓고, 주어진 조건에 만족하는 결과를 찾는 것
조건을 만족할 경우에만 값을 기록
/*
Copyright 2022 Ryan M. Jeong <[email protected] >
*/
// CP
#define CP do { \
std::ios::sync_with_stdio (false ); \
std::cin.tie (NULL ); \
} while (0 )
#include < iostream>
#include < vector>
#include < algorithm>
int main () {
CP;
// 최적화 문제: 랜선 n개를 만들 때 각 랜선의 최대 길이
// 결정 문제: 각 랜선의 길이가 x일 때, 랜선이 n개 이상인가? (최대)
int k, n;
std::cin >> k >> n;
std::vector<int > v (k);
for (int i = 0 ; i < k; ++i)
std::cin >> v[i];
std::sort (v.begin (), v.end ());
int res = 0 ;
int64_t low = 1 ;
int64_t high = static_cast <int64_t >(v.back ()) + 1 ; // [low, high)
while (low < high) {
int64_t mid = (low + high) / 2 ;
int cnt = 0 ;
for (const int & l : v)
cnt += l / mid;
if (cnt >= n) {
low = mid + 1 ;
res = mid;
} else {
high = mid;
}
}
std::cout << res;
return 0 ;
}