https://www.acmicpc.net/problem/3020
풀이
석순과 종유석이 번갈아 나오는 동굴을 장애물을 파괴하면서 지나가야한다.
높이별로 만나는 장애물의 개수를 세어 최솟값을 찾는 문제이다.
처음에 누적합으로 문제를 풀었고, 이분 탐색으로 푸는 방법이 있다고하여 찾아보았다.
- 이분 탐색
이분 탐색으로 풀기 위해서는 석순과 종유석을 따로 배열에 담아준다.
bottom배열에 석순을, top배열에 종유석을 담았다.
이분탐색을 위해 배열을 정렬한 뒤 1부터 H까지 높이을 key로 하여 이분탐색을 진행한다.
석순과 종유석을 각각 진행하여 해당 key값(key값보다 크거나 같은 첫번째 인덱스)을 찾아 arr.length - rigth을 반환하면 해당 구간의 장애물의 개수를 구할 수 있다.
- 누적 합
누적 합으로 풀기 위해 우선 높이를 length로 하는 배열을 만들고 입력받으면서 [석순의 높이]를 인덱스로 하는 값을 증가시키고,
종유석의 경우 [높이 - 종유석의 높이]의 값을 감소, [높이]의 값을 증가시킨다.
입력 후 H부터 하향식 탐색하며 arr[i] += arr[i + 1]하여 누적 합해준다.
누적 합이 된 배열을 탐색하여 최솟값을 찾는다.
이분 탐색
메모리: 34068KB
시간: 616ms
언어: Java 11
import java.io.*;
import java.util.*;
public class Main {
public static void main(String[] args) throws IOException {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
StringTokenizer st = new StringTokenizer(br.readLine());
int N = Integer.parseInt(st.nextToken());
int H = Integer.parseInt(st.nextToken());
int[] bottom = new int[N / 2];
int[] top = new int[N / 2];
for (int i = 0; i < N / 2; i++) {
bottom[i] = Integer.parseInt(br.readLine());
top[i] = Integer.parseInt(br.readLine());
}
Arrays.sort(bottom);
Arrays.sort(top);
int min = Integer.MAX_VALUE;
int cnt = 0;
for (int i = 1; i < H + 1; i++) {
int tmp = binarySearch(0, N / 2, i, bottom) + binarySearch(0, N / 2, H - i + 1, top);
if (tmp < min) {
min = tmp;
cnt = 1;
} else if (tmp == min) {
cnt++;
}
}
System.out.println(min + " " + cnt);
}
private static int binarySearch(int left, int right, int key, int[] arr) {
while (left < right) {
int mid = (left + right) / 2;
if (arr[mid] >= key) {
right = mid;
} else {
left = mid + 1;
}
}
return arr.length - right;
}
}
누적 합
메모리: 29272KB
시간: 320ms
언어: Java 11
import java.io.*;
import java.util.*;
public class Main {
public static void main(String[] args) throws IOException {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
StringTokenizer st = new StringTokenizer(br.readLine());
int N = Integer.parseInt(st.nextToken());
int H = Integer.parseInt(st.nextToken());
int[] arr = new int[H + 1];
for (int i = 0; i < N; i++) {
int a = Integer.parseInt(br.readLine());
if (i % 2 == 0) {
arr[a]++;
} else {
arr[H - a]--;
arr[H]++;
}
}
for (int i = H - 1; i > 0; i--) {
arr[i] += arr[i + 1];
}
int min = Integer.MAX_VALUE;
int cnt = 0;
for (int i = 1; i < H + 1; i++) {
if (arr[i] < min) {
min = arr[i];
cnt = 1;
} else if (arr[i] == min) {
cnt++;
}
}
System.out.println(min + " " + cnt);
}
}
'Algorithm > Baekjoon' 카테고리의 다른 글
[백준] 13334: 철로 - JAVA (0) | 2024.05.16 |
---|---|
[백준] 1525: 퍼즐 - JAVA (1) | 2024.05.15 |
[백준] 14867: 물통 - JAVA (0) | 2024.05.14 |
[백준] 9081: 단어 맞추기 - JAVA (0) | 2024.05.14 |
[백준] 2250: 트리의 높이와 너비 - JAVA (0) | 2024.05.14 |
[백준] 3025: 돌 던지기 - JAVA (0) | 2024.05.14 |