읽기 전
- 불필요한 코드나 잘못 작성된 내용에 대한 지적은 언제나 환영합니다.
- 개인적으로 배운 점을 정리한 글입니다.
문제 링크
문제 풀이
주어진 범위에 대해 완전 탐색을 진행하나 해당 구간에서 부딪히는 장애물의 수를 구하는 과정을 이진 탐색을 사용해 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 |