[백준 G5] 개똥벌레 (3020번)
3020번: 개똥벌레
개똥벌레 한 마리가 장애물(석순과 종유석)로 가득찬 동굴에 들어갔다. 동굴의 길이는 N미터이고, 높이는 H미터이다. (N은 짝수) 첫 번째 장애물은 항상 석순이고, 그 다음에는 종유석과 석순이
www.acmicpc.net
문제
개똥벌레 한 마리가 장애물(석순과 종유석)로 가득찬 동굴에 들어갔다. 동굴의 길이는 N미터이고, 높이는 H미터이다. (N은 짝수) 첫 번째 장애물은 항상 석순이고, 그 다음에는 종유석과 석순이 번갈아가면서 등장한다.
아래 그림은 길이가 14미터이고 높이가 5미터인 동굴이다. (예제 그림)
이 개똥벌레는 장애물을 피하지 않는다. 자신이 지나갈 구간을 정한 다음 일직선으로 지나가면서 만나는 모든 장애물을 파괴한다.
위의 그림에서 4번째 구간으로 개똥벌레가 날아간다면 파괴해야하는 장애물의 수는 총 여덟개이다. (4번째 구간은 길이가 3인 석순과 길이가 4인 석순의 중간지점을 말한다)
하지만, 첫 번째 구간이나 다섯 번째 구간으로 날아간다면 개똥벌레는 장애물 일곱개만 파괴하면 된다.
동굴의 크기와 높이, 모든 장애물의 크기가 주어진다. 이때, 개똥벌레가 파괴해야하는 장애물의 최솟값과 그러한 구간이 총 몇 개 있는지 구하는 프로그램을 작성하시오.
입력
첫째 줄에 N과 H가 주어진다. N은 항상 짝수이다. (2 ≤ N ≤ 200,000, 2 ≤ H ≤ 500,000)
다음 N개 줄에는 장애물의 크기가 순서대로 주어진다. 장애물의 크기는 H보다 작은 양수이다.
출력
첫째 줄에 개똥벌레가 파괴해야 하는 장애물의 최솟값과 그러한 구간의 수를 공백으로 구분하여 출력한다.
예제 입력
14 5
1
3
4
2
2
4
3
4
3
3
3
2
3
3
예제 출력
7 2
소스코드 및 풀이
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
int main(void)
{
ios_base::sync_with_stdio(0);
cin.tie(0);
cout.tie(0);
int N, H;
cin >> N >> H;
vector<int> bottom(N/2), top(N/2);
for(int i = 0; i< N/2; ++i)
cin >> bottom[i] >> top[i];
sort(bottom.begin(), bottom.end());
sort(top.begin(), top.end());
int min = -1;
int cnt = 1;
for(int i = 1; i<=H; ++i) {
int down = lower_bound(bottom.begin(), bottom.end(), i) - bottom.begin();
int up = upper_bound(top.begin(), top.end(), H-i) - top.begin();
int sum = bottom.size() - down;
sum += top.size() - up;
if(min == sum) {
cnt ++;
}
else if(min == -1 || min > sum) {
min = sum;
cnt = 1;
}
}
cout << min << " " << cnt << "\n";
return 0;
}
* 역시 골드 문제는 아직 어렵다. 뭣보다 시간초과 때문에 꽤나 고생을 했던 문제이다. 정렬하면 터질 줄 알았는데 의외로 안터졌다.
* 전략은 위와 아래를 따로 생각한다는 점과 입력받은 순서는 상관이 없기때문에 정렬을 한 후 갯수를 세는 것이다. 이때 갯수를 그냥 for문 돌면서 세면 시간초과가 나는데 lower_bound, upper_bound 혹은 이분탐색을 통해서 갯수를 셈으로써 시간을 줄여야한다.