import sys
def input():
return sys.stdin.readline().rstrip()
def check(mid):
idx = 0
temp = []
cnt = 0
while idx<N:
if cnt >M:
return False
if temp:
min_value,max_value = min(temp),max(temp)
if abs(arr[idx]-min_value)>mid or abs(arr[idx]-max_value)>mid:
cnt += 1
temp = [arr[idx]]
else:
temp.append(arr[idx])
else:
temp.append(arr[idx])
idx += 1
if temp:
cnt += 1
if cnt>M:
return False
return True
N,M = map(int,input().split())
arr = list(map(int,input().split()))
left = -1
right = 10001
while left+1<right:
mid = (left+right)//2
if check(mid):
right = mid
else:
left = mid
print(right)
이 문제는 구간의 최대값과 최소값을 비교한 값이 최대가 되어야하고 M개 이하의 그룹으로 나뉘어야한다.
이 문제를 푸는 법은 이분탐색을 이용해서 풀면된다. 이분탐색의 탐색근거가 되는 값은 최대-최소의 값이다.
이 값이 벗어나는 경우 새로운 그룹을 만들어주고, 총 그룹의 수가 M개 초과가 되면 False를 만족하면 True로 하면서
True를 만족 최소의 값을 구하면 된다.
위의 풀이는 list에 계속 넣다 빼다보니 시간이 좀 오래걸린다.
import sys
def input():
return sys.stdin.readline().rstrip()
def check(mid):
min_value = arr[0]
max_value = arr[0]
idx = 1
cnt = 1
while idx<N:
if cnt>M:
return False
if min_value>arr[idx]:
min_value = arr[idx]
if max_value < arr[idx]:
max_value = arr[idx]
if max_value-min_value>mid:
min_value = arr[idx]
max_value = arr[idx]
cnt += 1
idx += 1
if cnt>M:
return False
else:
return True
N,M = map(int,input().split())
arr = list(map(int,input().split()))
left = -1
right = 10001
while left+1<right:
mid = (left+right)//2
if check(mid):
right = mid
else:
left = mid
print(right)
똑같은 원리지만, 훨씬 빠른 풀이다. 리스트를 저장하는게 아니라, 최소 최대값을 계속 갱신을 해주면서,
그 값이 주어진 mid보다 크면, 최소 최대값을 현재 탐색중인 값으로 초기화 해준뒤 cnt를 늘려주면 된다.
이 풀이가 좀 더 깔끔한 풀이라 생각한다.
'알고리즘 > 백준' 카테고리의 다른 글
[BOJ/백준] 16437 양 구출 작전 (0) | 2021.07.12 |
---|---|
[BOJ/백준] 13711 LCS 4 (0) | 2021.07.12 |
[BOJ/백준] 4358 생태학 (0) | 2021.07.12 |
[BOJ/백준] 16947 서울 지하철 2호선 (0) | 2021.07.12 |
[BOJ/백준] 16472 고냥이 (0) | 2021.06.29 |