"""
author : Park Min Hyeok
github : https://github.com/m1nnh
e-mail : alsgur9784@naver.com
title : 개똥벌레
description : 부분합
"""
N, H = map(int, input().split())
Cave = [int(input()) for _ in range(N)]
A = [0] * (H + 2)
B = [0] * (H + 2)
result = [0] * (H + 2)
for i in range(N):
h = Cave[i]
if i % 2 == 0:
B[h + 1] += 1
else:
A[H - h] += 1
for i in range(2, H + 1):
B[i] += B[i - 1]
for i in range(H, -1, -1):
A[i] += A[i + 1]
for i in range(1, H + 1):
result[i] = A[i] + B[i]
print(N - max(result), result.count(max(result)))
땅에서 천장 방향으로 높이를 1
씩 증가하면서 부딪히는 갯수를 세게 되면
1)석순의 경우, 석순의 높이보다 1
높아지는 지점에서 해당 석순에 부딪히지 않게되므로, 부딪히는 갯수가 1 줄어들게 됩니다.
2) 종유석의 경우, h - 종유석
의 길이보다 1
높아지는 지점에서 해당 종유석에 부딪히게 되므로, 부딪히는 갯수가 1
늘어나게 됩니다.
3) 1) 속성을 이용하여 각 높이로 변경 될 때, 몇개의 장애물이 새로 부딪히는지, 덜 부딪히게 되는지를 배열에 저장합니다.
4) 2)에서 구한 배열을 가지고, 0 ~ h까지 누적 합들을 구하면서, 최소로 부딪히는 값과 그 구간의 갯수를 구한다.
n, h = map(int, input().split())
down = []
up = []
for i in range(n):
if i % 2 == 0:
down.append(int(input()))
else:
up.append(int(input()))
down.sort()
up.sort()
min_count = n
range_count = 0
def binary_search(array, target, start, end):
while start <= end:
mid = (start + end) // 2
if array[mid] < target:
start = mid + 1
else:
end = mid - 1
return start
for i in range(1, h + 1):
down_count = len(down) - binary_search(down, i - 0.5, 0, len(down) - 1)
top_count = len(up) - binary_search(up, h - i + 0.5, 0, len(up) - 1)
if min_count == down_count + top_count:
range_count += 1
elif min_count > down_count + top_count: # 현재 범위가 새로운 최소 값이면
range_count = 1
min_count = down_count + top_count
print(min_count, range_count)
장애물이 설치된 동굴에 개똥벌레 한마리가 날라가는데 동굴의 높이가 6일 때, 개똥벌레가 날아가는 높이가 3이라고 한다면 아래에서부터 높이 2~3 (2.5라고 생각하면 쉽다) 구간을 날라간다.
그래서 3보다 낮은 석순에는 모두 부딪히게 되고, 3보다 큰 종유석에는 모두 부딪히게 된다. ( 위에서 부터 4 만큼 내려온 종유석에는 아래에서 부터 2.5만큼 날아오른 개똥벌레가 부딪히기 때문)
왜냐하면, 높이 6의 동굴에서 높이 2짜리 종유석은 높이 4 (실질적으로 3.5) 위로의 개똥벌레가 모두 부딪히기 때문이다.
개똥벌레가 파괴해야 하는 장애물의 최소 개수와 이 최소값이 나오는 구간의 수를 구하는 것이다.
보통의 이진탐색 과정과 마찬가지로 start값과 end값에 변화를 주며 mid값을 조정하여 개똥벌레가 최소한으로 부딪히는 구간을 찾으면 된다.
#include <cstdio>
int n, h, answer, count;
int sum[500010];
int main() {
scanf("%d %d", &n, &h);
for (int i = 0 ; i < n ; i++) {
int bar;
scanf("%d", &bar);
if (i & 1) {
// 종유석
sum[h - bar + 1]++;
}
else {
// 석순
sum[1]++;
sum[bar + 1]--;
}
}
answer = -1;
for (int i = 1 ; i <= h ; i++) {
sum[i] += sum[i - 1];
if (answer == -1 || sum[i] < answer) {
answer = sum[i];
count = 1;
}
else if (sum[i] == answer) {
count++;
}
}
printf("%d %d", answer, count);
}
#include <cstdio>
int n, h, answer, count;
int seok[200000], jong[200000];
// x구간으로 날아갈때 k번째 석순과 만나는지
bool check_seok(int k, int x) {
if (x <= seok[k]) return true;
return false;
}
// x구간으로 날아갈때 k번째 종유석과 만나는지
bool check_jong(int k, int x) {
if (h - jong[k] + 1 <= x) return true;
return false;
}
int fly(int x) {
int res = 0;
for (int i = 0 ; i < n ; i += 2) {
// 석순과 만나는지
if (check_seok(i, x)) res++;
// 종유석과 만나는지
if (check_jong(i, x)) res++;
}
return res;
}
int main() {
scanf("%d %d", &n, &h);
for (int i = 0 ; i < n ; i += 2) {
scanf("%d", &seok[i]);
scanf("%d", &jong[i]);
}
answer = -1;
for (int i = 1 ; i <= h ; i++) {
int crash = fly(i);
if (answer == -1 || crash < answer) {
answer = crash;
count = 1;
}
else if (crash == answer) {
count++;
}
}
printf("%d %d", answer, count);
}