BOJ_C++_PS
[BOJ/13397번구간나누기2] c++ / binary_serach
leebaek
2023. 11. 13. 21:09
문제
주어진 배열에서 M개 이하의 구간을 만들 때, 각 구간의 값(최댓값과 최솟값)의 최댓값 중 최솟값을 구하는 문제
생각
0부터 배열에서 가장 큰 값까지 이분 탐색을 이용해야겠다 생각함
구간의 최댓값-최솟값이 mid보다 크면 cnt값을 늘려서 M보다 큰지 작은지 비교하면 됨
문제풀이
1.st=0, en=배열에서 가장 큰 값으로 두고 이분 탐색 시작
2.배열을 돌면서 구간마다 최솟값, 최댓값 갱신해줌
3.만약 최댓값-최솟값이 Mid보다 크다면, cnt++ | 최댓값 = 현재 배열값 / 최솟값 = 현재 배열값으로 초기화해줌 ( 다음 구간으로 넘어갔다고 생각하면 됨 )
4.만약 cnt가 M보다 커진다면 ck = 1 하고 break 해줌
5.만약 cnt가 M보다 크거나 ck == 1 일 경우, st = mid + 1 - 더 큰 값에서 탐색해야함
5-1.만약 cnt가 M과 같거나 작을 경우, result = mid 저장하고 en = mid - 1 - 더 작은 값에서 탐색해야함
6.result 출력 ( 초기값은 배열에서 가장 큰 수 ) - ( 배열의 크기가 1이면 mid값이 설정이 안되기 때문
코드
#include <iostream>
#include <algorithm>
using namespace std;
int N, M, min_N=10000, max_N=0;
int arr[5001];
int main() {
ios::sync_with_stdio(0);
cin.tie(0);
cin >> N >> M;
for ( int i = 0; i < N; i++ ) {
cin >> arr[i];
min_N = min(min_N, arr[i]);
max_N = max(max_N, arr[i]);
}
int st = 0, en = max_N, result=en;
while ( st <= en ) {
int mid = ( st + en ) / 2;
int cnt = 1, ck=0;
int i_s=arr[0], i_e=arr[0];
for ( int i = 1; i < N; i++ ) {
i_e = max(i_e, arr[i]);
i_s = min(i_s, arr[i]);
if ( i_e - i_s > mid ) {
i_s = arr[i];
i_e = arr[i];
cnt++;
}
if ( cnt > M ) {
ck = 1;
break;
}
}
if ( cnt > M || ck == 1 )
st = mid + 1;
else {
result = mid;
en = mid - 1;
}
}
cout << result;
}