※ 글쓴이는 취미로 코딩을 익혀보는 사람이라 정확하지 않은 내용을 담고 있을 수 있다 ※
이번에 볼 문제는 백준 2696번 문제인 중앙값 구하기이다.
문제는 아래 링크를 확인하자.
https://www.acmicpc.net/problem/2696
2696번: 중앙값 구하기
첫째 줄에 테스트 케이스의 개수 T(1 ≤ T ≤ 1,000)가 주어진다. 각 테스트 케이스의 첫째 줄에는 수열의 크기 M(1 ≤ M ≤ 9999, M은 홀수)이 주어지고, 그 다음 줄부터 이 수열의 원소가 차례대로 주
www.acmicpc.net
2k-1개의 수를 지금까지 읽었을 때 각 수들은 (중앙값 이하의 k-1개의 수), 중앙값, (중앙값 이상의 k-1개의 수)와 같이 들고 관리하고 있을 수 있다.
이 상태에서 두 개의 수가 더 추가될 때, 두 수중 하나는 중앙값 이하이고 하나는 중앙값 이상이라면 각 값을 중앙값 이하의 수의 모임과 이상의 수의 모임에 집어넣어 위의 형태를 유지할 수 있다.
두 값이 모두 중앙값 이상인 경우, 현재의 중앙값을 중앙값 이하의 수의 모임으로 옮기고 두 값과 중앙값 이상의 k-1개의 수 중 가장 작은 수를 중앙값으로 한 뒤 남은 수를 중앙값 이상의 수의 모임으로 하면 위의 형태를 유지할 수 있다. 이는 두 값이 모두 중앙값 이하인 경우에도 비슷하게 적용할 수 있다.
위와 같은 관리를 효율적으로 하기 위해 우선순위 큐(priority queue) 자료구조를 이용할 수 있다. 이를 이용해 문제를 해결하자.
int형을 관리하는 우선순위 큐에 각 수를 음의 부호를 붙여 max heap을 min heap처럼 이용할 경우 -2^31에 음의 부호를 붙이면 코드가 의도대로 작동하지 않을 수 있음에 유의하자. (-2^31은 int형의 범위에 포함되지만, 2^31은 int형이 표현할 수 있는 범위에 포함되지 않는다는 점을 상기하자.)
또한, 문제의 답을 출력할 때 정수를 10개 단위로 끊어서 출력해야함에 유의하자.
아래는 제출한 소스코드이다.
#include <iostream>
#include <queue>
#include <utility>
using namespace std;
typedef long long ll;
void solve() {
int N; cin >> N;
cout << N / 2 + 1 << '\n';
ll mid; cin >> mid;
cout << mid << ' ';
priority_queue<ll> L, R;
N >>= 1;
int cnt = 1;
while (N--) {
ll x, y; cin >> x >> y;
if (x > y) swap(x, y);
if (y <= mid) {
R.push(-mid);
L.push(x); L.push(y);
mid = L.top(); L.pop();
}
else if (mid <= x) {
L.push(mid);
R.push(-x); R.push(-y);
mid = -R.top(); R.pop();
}
else L.push(x), R.push(-y);
if (cnt == 10) cnt = 0, cout << '\n';
cout << mid << ' ';
cnt++;
}
cout << '\n';
}
int main() {
ios::sync_with_stdio(0);
cin.tie(0);
int T; cin >> T;
while (T--) solve();
}
'BOJ' 카테고리의 다른 글
[BOJ 2694 // C++] 합이 같은 구간 (0) | 2023.04.20 |
---|---|
[BOJ 2695 // C++] 공 (0) | 2023.04.19 |
[BOJ 14600 // C++] 샤워실 바닥 깔기 (Small) (0) | 2023.04.17 |
[BOJ 14601 // C++] 샤워실 바닥 깔기 (Large) (0) | 2023.04.16 |
[BOJ 2250 // C++] 트리의 높이와 너비 (0) | 2023.04.15 |