※ 글쓴이는 취미로 코딩을 익혀보는 사람이라 정확하지 않은 내용을 담고 있을 수 있다 ※

 

이번에 볼 문제는 백준 7662번 문제인 이중 우선순위 큐이다.
문제는 아래 링크를 확인하자.

www.acmicpc.net/problem/7662

 

7662번: 이중 우선순위 큐

입력 데이터는 표준입력을 사용한다. 입력은 T개의 테스트 데이터로 구성된다. 입력의 첫 번째 줄에는 입력 데이터의 수를 나타내는 정수 T가 주어진다. 각 테스트 데이터의 첫째 줄에는 Q에 적

www.acmicpc.net

우선순위 큐(priority queue)는 자료의 추가가 수시로 이루어지는 경우, 우선순위가 가장 높은(또는 낮은) 자료를 항상 빠르게 꺼낼 수 있는 자료구조이다.

 

이 문제에서는 쿼리를 통해 자료를 빈번히 추가하고 우선순위가 가장 높은 자료 또는 가장 낮은 자료를 쿼리가 들어온 시점을 기준으로 제거한다.

이런 작업을 수행할 수 있는 우선순위 큐를 double-ended priority queue라고 한다.

 

double-ended priority queue를 구현하는 대표적인 방법 중 하나는 min-max heap을 이용하는 것이다.

그러나 이 문제는 자료구조를 처음서부터 코딩하라는 문제가 아니기에 글쓴이는 min-max heap을 직접 구현하지는 않았다.

min-max heap에 관심이 있다면 다음 위키백과 링크를 참고하자.

en.wikipedia.org/wiki/Min-max_heap

 

글쓴이는 stl에 들어있는 std::priority_queue를 활용하여 문제를 풀었다.

 

std::priority_queue는 max heap 자료구조인데, 정수 자료의 경우 자료를 넣을 때 -1을 곱해 넣고 꺼낼 때 다시 -1을 곱하는 방식으로 min heap으로도 사용할 수 있다.

(단, 일반적인(signed) int형의 경우 양수와 음수가 완전히 대응되지 않으므로 이에 주의한다.)

 

문제를 푼 방식은 단순하다.

 

1) 새로운 정수가 들어온다면 이 정수를 max heap과 min heap에 각각 넣는다.

 

2-1) 최댓값을 지우라는 명령이 들어오면 max heap에서 최댓값을 지우고, min heap에서 다음에 이 수가 나오면 지워야 한다고 기록해둔다. 이 수들은 min heap에서 숫자가 지워지는 순서대로 만나게 될 것이므로, 또 다른 min heap에 저장해두면 지워야 할 때 쉽게 확인하고 지울 수 있다.

 

2-2) 최솟값을 지우라는 명령이 들어오면 min heap서 최솟값을 지우고, max heap에서 다음에 이 수가 나오면 지워야 한다고 기록해둔다. 이 수들은 max heap에서 숫자가 지워지는 순서대로 만나게 될 것이므로, 또 다른 max heap에 저장해두면 지워야할 때 쉽게 확인하고 지울 수 있다.

 

3) max heap과 min heap에서 지워야 할 수를 모두 지운다.

 

4) 1~3을 반복한다.

 

아래는 제출한 소스코드이다.

#include <iostream>
#include <queue>
using std::priority_queue;
using std::cin;
using std::cout;

void solve() {
    priority_queue<long long> mxpq;
    priority_queue<long long> mxpqchk;
    priority_queue<long long> mnpq;
    priority_queue<long long> mnpqchk;
    
    int k;
    cin >> k;
    
    char type;
    long long n;
    for (int i = 0;i < k;i++) {
        cin >> type >> n;
        if (type == 'I') {
            mxpq.push(n);
            mnpq.push(-1*n);
        }
        else {
            if (n == 1 and mxpq.size()!=0) {
                long long x = mxpq.top();
                mnpqchk.push(-1*x);
                mxpq.pop();
            }
            else if (n == -1 and mnpq.size()!=0) {
                long long x = -1*mnpq.top();
                mxpqchk.push(x);
                mnpq.pop();
            }
            int sz1 = mxpq.size();
            int sz2 = mxpqchk.size();
            while (sz1 != 0 and sz2 != 0) {
                if (mxpq.top() == mxpqchk.top()) {
                    mxpq.pop();
                    mxpqchk.pop();
                    sz1 = mxpq.size();
                    sz2 = mxpqchk.size();
                }
                else break;
            }
            sz1 = mnpq.size();
            sz2 = mnpqchk.size();
            while (sz1 != 0 and sz2 != 0) {
                if (mnpq.top() == mnpqchk.top()) {
                    mnpq.pop();
                    mnpqchk.pop();
                    sz1 = mnpq.size();
                    sz2 = mnpqchk.size();
                }
                else break;
            }
        }
    }
    if (mxpq.size()==0) cout << "EMPTY\n";
    else cout << mxpq.top() << ' ' << -1*mnpq.top() << "\n";
}

int main()
{
    std::ios::sync_with_stdio(0);
    cin.tie(0);

    int T;
    cin >> T;
    for (int i = 0;i < T;i++) {
        solve();
    }

    return 0;
}
728x90

'BOJ' 카테고리의 다른 글

[BOJ 14686 // C++] Sum Game  (0) 2021.02.07
[BOJ 1107 // C++] 리모컨  (0) 2021.02.06
[BOJ 1780 // C++] 종이의 개수  (0) 2021.02.04
[BOJ 7569 // C++] 토마토  (0) 2021.02.03
[BOJ 16236 // C++] 아기 상어  (0) 2021.02.02

+ Recent posts