https://www.acmicpc.net/problem/7662
7662번: 이중 우선순위 큐
입력 데이터는 표준입력을 사용한다. 입력은 T개의 테스트 데이터로 구성된다. 입력의 첫 번째 줄에는 입력 데이터의 수를 나타내는 정수 T가 주어진다. 각 테스트 데이터의 첫째 줄에는 Q에 적
www.acmicpc.net
문제
풀이
가장 큰 값과 가장 작은 값을 명령어에 따라 삭제해야 하는 문제입니다.
우선순위 큐라는 단어에 휩싸여서 처음에는 max heap 형태의 pq를 통해 top(max값) 을 구하고, 마지막 원소를 제외하고 또 다 pop을 하여 min값을 구하는 식으로 구현했는데, 그런식으로 하면 시간초과가 났습니다.
min값을 구하기 위해서 기존 원소들을 다 제거하는 방식이었으므로 logN + logN-1 + ... log1 번의 연산이 필요했습니다.
→ 즉 max값과 min값을 logN 정도로는 구해야 시간초과가 나지 않을 것이라 판단했습니다.
따라서 이 문제에서 말하는 것은 이중 우선순위 큐 이지만, 최대값과 최소값 둘 다를 빠르게 접근하기 위해 Multi Set을 사용하겠습니다.
(우선순위 큐는 우선순위가 가장 높은 값 하나만을 탐색하기에 적합합니다.)
< multiset의 특징 >
1. set이면서도 원소가 중복됨을 허용합니다.
2. BST(이진 탐색 트리)구조로 기본적으론 오름차순 정렬을 합니다.
(또한 AVL 트리 구조여서 탐색 시간은 O(logN)을 보장합니다)
즉 항상 multiset의 begin()에는 최소값이, --end() (end()가 아닌 그 앞에 마지막 원소가 존재합니다)에는 최대값이 존재하게 됩니다.
이를 이용하여 D 1 일 땐 multiset.erase(--multiset.end()), D -1 일 땐 multiset.erase(multiset.begin()) 을 진행합니다.
코드
#include<iostream>
#include<set>
using namespace std;
int main() {
ios::sync_with_stdio(false);
cin.tie(NULL);
int t, k, n;
char ins;
cin >> t;
while (t--) {
multiset<int> ms;
cin >> k;
while (k--) {
cin >> ins >> n;
if (ins == 'I') {
ms.insert(n);
}
else {
if (ms.empty()) continue;
if (n == 1) {
ms.erase(--ms.end());
}
else {
ms.erase(ms.begin());
}
}
}
if (ms.empty()) cout << "EMPTY\n";
else {
cout << *(--ms.end()) << " " << *ms.begin() << "\n";
}
}
return 0;
}
'알고리즘' 카테고리의 다른 글
[C++] 백준 - 5430번 : AC (2) | 2023.03.08 |
---|---|
[C++] 백준 - 1202 : 보석 도둑 (0) | 2023.03.07 |
[C++] 백준 - 1655 : 가운데를 말해요 (0) | 2023.02.28 |
[C++] 백준 - 1715번 : 카드 정렬하기 (0) | 2023.02.28 |
[C++] 백준 - 1181번 : 단어 정렬 (0) | 2023.02.26 |