C++/백준 문제풀이
C++ [가운데를 말해요_백준] / #priority_queue
공부하는 신입사원
2023. 3. 29. 18:43
Problem

- 보기에는 간단해보이지만 쉽지 않은 문제였다.
- 처음은 vector에 수를 넣고 넣을때마다 sort를 통해 정렬한 뒤 vec[i/2]로 가운데 인자에 접근했었으나 시간초과로 계속 실패했었다.
- 구글링을 통해 힌트를 얻어 해결하였다.
- 풀이법은 간단하면서 획기적이어서 충격이었다.
Solve
- 우선 priority_queue 2개가 필요하다.
- 하나는 중간값보다 작은 수들이 들어갈 우선순위 큐(작은 큐), 다른 하나는 중간값보다 큰 수가 들어갈 우선순위 큐(큰 큐)이다.
- 수가 들어올 때 작은 큐와 큰 큐에 번갈아가며 넣으면 된다. 단, 이 때 규칙이있다.
- 중간값은 항상 작은 큐의 top()에 위치한다.
- 작은 큐의 사이즈는 큰 큐의 사이즈와 같거나 1만큼만 차이나야한다.
- 큰 큐 -> 내림차순 / 작은 큐 -> 오름차순 이어야한다.

- 그림과 같은 경우를 보면 4가 들어왔을 때 두 큐의 사이즈가 같으면 작은 큐에 우선으로 넣으면 된다. 그러면 자연스럽게 작은 큐의 top()이 중간값이 된다.

- 단, 고려해야하는 경우들이 있다. 예를 들어 위와 같은 상황에서 이번에는 9가 들어온다고 생각해보자
- 두 큐의 사이즈가 같다고 작은 큐에 넣으면 작은 큐의 top()이 9가 되어버린다. 따라서 이런경우 큰 큐의 top()인 5를 작은 큐에 push()하고 큰 큐를 pop()한 뒤 9를 큰 큐에 넣어주면된다. 이 때의 중간 값은 작은 큐의 top()인 5가 된다.
#include <iostream>
#include <queue>
using namespace std;
priority_queue<int, vector<int>, greater<int>> a; // mid보다 큰 값들
priority_queue<int> b; // mid보다 작은 값들
void qinsert(int num)
{
if (b.size() > a.size())
{
if (b.empty())
{
a.push(num);
}
else if (b.top() > num)
{
a.push(b.top());
b.pop();
b.push(num);
}
else
{
a.push(num);
}
}
else
{
if (a.empty())
{
b.push(num);
}
else if (a.top() < num)
{
b.push(a.top());
a.pop();
a.push(num);
}
else
{
b.push(num);
}
}
}
int main()
{
ios::sync_with_stdio(false);
cin.tie(NULL);
cout.tie(NULL);
int N,num;
cin >> N;
int* arr = new int[N];
for (int i = 0; i < N; i++)
{
cin >> num;
qinsert(num);
cout << b.top() << '\n';
}
return 0;
}
문제 링크