읽기 전
- 불필요한 코드나 잘못 작성된 내용에 대한 지적은 언제나 환영합니다.
- 개인적으로 배운 점을 정리한 글입니다.
문제 링크
문제 풀이
주어진 범위에 대해 완전 탐색을 진행하나 해당 구간에서 부딪히는 장애물의 수를 구하는 과정을 이진 탐색을 사용해 $O(log\ n)$으로 줄임으로써 전체 시간복잡도를 $O(nlog\ n)$으로 만들어야 한다. 특히 이 문제는 binary search의 lower bound와 upper bound를 제대로 이해하면 바로 해결할 수 있었다.
- 항상 홀수 번은 석순, 짝수 번은 종유석이고 N은 언제나 짝수이므로 절반으로 나눠 두 배열에 별도로 입력받는다.
- 구간 h는 높이 h-1과 h 사이를 의미하므로 탐색은 1부터 H까지 진행한다.
- 따라서 1부터 H까지 순회한다고 할 때 석순은 h와 같거나 큰 개수이고(lower bound) 종유석은 H - [종유석 길이] < h (upper bound)를 만족하는 개수이다.
- bound를 다루는 두 개의 함수를 둘 필요 없이 석순의 경우 h번째 구간일 때 h-1에 대한 upper bound를 판별하면 종유석과 함께 같은 함수를 사용할 수 있다.
- 부딪히는 종유석, 석순의 개수는 각 장애물 개수 - upper bound 좌표가 되겠다.
- 모든 구간에 대해 순회하면서 최소값을 갱신하여 카운트한 뒤 결과를 리턴하면 된다.
python 코드
import sys
input = sys.stdin.readline
N, H = map(int, input().split())
suck, jong = [], []
for _ in range(N // 2):
suck.append(int(input()))
jong.append(int(input()))
def search(arr, val): # upper bound 판별
l, r = 0, len(arr)
while l < r:
mid = l + (r - l) // 2
if arr[mid] > val:
r = mid
elif arr[mid] <= val:
l = mid + 1
return len(arr) - l # val보다 작은 값 제외한 나머지
suck.sort()
jong.sort()
min_v, sol = N, 0
for h in range(1, H + 1):
s = search(suck, h - 1) + search(jong, H - h)
if s < min_v:
min_v = s
sol = 1
elif s == min_v:
sol += 1
print(min_v, sol)
'Algorithms > Baekjoon' 카테고리의 다른 글
BOJ #1463 1로 만들기 (0) | 2021.07.26 |
---|---|
BOJ #1149 RGB 거리 (0) | 2021.07.26 |
BOJ #2143 두 배열의 합 (0) | 2021.07.17 |
BOJ #12015 가장 긴 증가하는 부분 수열 2 (0) | 2021.07.15 |
BOJ #1655 가운데를 말해요 (0) | 2021.07.15 |