※ 글쓴이는 취미로 코딩을 익혀보는 사람이라 정확하지 않은 내용을 담고 있을 수 있다 ※
이번에 볼 문제는 백준 1655번 문제인 가운데를 말해요이다.
문제는 아래 링크를 확인하자.
1655번: 가운데를 말해요
첫째 줄에는 수빈이가 외치는 정수의 개수 N이 주어진다. N은 1보다 크거나 같고, 100,000보다 작거나 같은 자연수이다. 그 다음 N줄에 걸쳐서 수빈이가 외치는 정수가 차례대로 주어진다. 정수는 -1
www.acmicpc.net
이 문제에서는 매번 목록에 새로운 수가 하나씩 추가될 때, 그 목록의 크기순으로 중간번째인 수를 출력해야 한다. 만약 숫자가 짝수라면, 가운데에서 작은 수를 골라 출력해야 한다. 예를 들면 8개의 수 가운데 4번째로 작은 수를 출력해야 한다.
이 문제를 풀기 위해서는 다른 위치에 상관 없이 크기순으로 중간에 있는 값에만 빠르게 접근하면 되므로, 목록을 출력해야하는 중간번째를 기준으로 나눠서 중간번째보다 큰 수를 보관하는 우선순위 큐(priority queue)와 작은 수를 보관하는 우선순위 큐를 만드는 전략이 유효하다.
mid 변수에 기존 중간 위치의 값을 저장하자. 새로운 수를 입력받았을 때 이 값이 이전 출력값보다 크거나 같다면 큰 수를 보관하는 우선순위 큐에, 작다면 작은 수를 보관하는 우선순위 큐에 삽입한다. 그리고 두 우선순위 큐의 크기를 비교하면 현재 mid에 보관하고있는 값이 지금도 중간 위치에 있는 수인지 아닌지 알 수 있다.
mid에 보관된 값이 중간위치가 아니게 되었다면, mid를 적절한 우선순위 큐에 다시 넣고, 반대쪽 우선순위 큐에서 mid값을 새로 읽어온다.
아래는 제출한 소스코드이다.
#include <iostream>
#include <queue>
using std::cin;
using std::cout;
using std::priority_queue;
priority_queue<int> smallvalues;
int mid;
priority_queue<int> largevalues;
int main()
{
std::ios::sync_with_stdio(0);
cin.tie(0);
int N; cin >> N;
cin >> mid; cout << mid << '\n';
for (int i = 1;i < N;i++) {
int current; cin >> current;
if (current >= mid) largevalues.push(-current);
else smallvalues.push(current);
if (largevalues.size() - smallvalues.size() == 2) {
smallvalues.push(mid);
mid = -largevalues.top(); largevalues.pop();
}
else if (largevalues.size() - smallvalues.size() == -1) {
largevalues.push(-mid);
mid = smallvalues.top(); smallvalues.pop();
}
cout << mid << '\n';
}
return 0;
}
'BOJ' 카테고리의 다른 글
[BOJ 11046 // C++] 팰린드롬?? (0) | 2021.03.05 |
---|---|
[BOJ 10942 // C++] 팰린드롬? (0) | 2021.03.04 |
[BOJ 13975 // C++] 파일 합치기 3 (0) | 2021.03.02 |
[BOJ 14698 // C++] 전생했더니 슬라임 연구자였던 건에 대하여 (Hard) (0) | 2021.03.01 |
[BOJ 2691 // C++] 이항 쇼다운 (0) | 2021.02.28 |