🔗 문제 링크 : https://www.acmicpc.net/problem/7662
💀 12%에서 틀렸습니다!
이 경우는 문제에서 새로운 테스트케이스가 시작되면서 Q를 깨끗하게 비워주지 않아서 생기는 문제일 확률이 높다.
본인도 Q로 사용할 컨테이너를 선언하는 위치를 테스트케이스 "시작 전" -> 테스트케이스 "시작" 부분으로 옮겨서 문제를 해결하였다.
문제
이중 우선순위 큐(dual priority queue)는 전형적인 우선순위 큐처럼 데이터를 삽입, 삭제할 수 있는 자료 구조이다. 전형적인 큐와의 차이점은 데이터를 삭제할 때 연산(operation) 명령에 따라 우선순위가 가장 높은 데이터 또는 가장 낮은 데이터 중 하나를 삭제하는 점이다. 이중 우선순위 큐를 위해선 두 가지 연산이 사용되는데, 하나는 데이터를 삽입하는 연산이고 다른 하나는 데이터를 삭제하는 연산이다. 데이터를 삭제하는 연산은 또 두 가지로 구분되는데 하나는 우선순위가 가장 높은 것을 삭제하기 위한 것이고 다른 하나는 우선순위가 가장 낮은 것을 삭제하기 위한 것이다.
정수만 저장하는 이중 우선순위 큐 Q가 있다고 가정하자. Q에 저장된 각 정수의 값 자체를 우선순위라고 간주하자.
Q에 적용될 일련의 연산이 주어질 때 이를 처리한 후 최종적으로 Q에 저장된 데이터 중 최댓값과 최솟값을 출력하는 프로그램을 작성하라.
입출력 예시
입력
입력 데이터는 표준입력을 사용한다. 입력은 T개의 테스트 데이터로 구성된다. 입력의 첫 번째 줄에는 입력 데이터의 수를 나타내는 정수 T가 주어진다. 각 테스트 데이터의 첫째 줄에는 Q에 적용할 연산의 개수를 나타내는 정수 k (k ≤ 1,000,000)가 주어진다. 이어지는 k 줄 각각엔 연산을 나타내는 문자(‘D’ 또는 ‘I’)와 정수 n이 주어진다. ‘I n’은 정수 n을 Q에 삽입하는 연산을 의미한다. 동일한 정수가 삽입될 수 있음을 참고하기 바란다. ‘D 1’는 Q에서 최댓값을 삭제하는 연산을 의미하며, ‘D -1’는 Q 에서 최솟값을 삭제하는 연산을 의미한다. 최댓값(최솟값)을 삭제하는 연산에서 최댓값(최솟값)이 둘 이상인 경우, 하나만 삭제됨을 유념하기 바란다.
만약 Q가 비어있는데 적용할 연산이 ‘D’라면 이 연산은 무시해도 좋다. Q에 저장될 모든 정수는 -231 이상 231 미만인 정수이다.
출력
출력은 표준출력을 사용한다. 각 테스트 데이터에 대해, 모든 연산을 처리한 후 Q에 남아 있는 값 중 최댓값과 최솟값을 출력하라. 두 값은 한 줄에 출력하되 하나의 공백으로 구분하라. 만약 Q가 비어있다면 ‘EMPTY’를 출력하라.

풀이
이중 우선순위 큐를 구현하는 문제이다.
테스트케이스에서 값을 삽입 및 삭제 기능을 수행하여야 하는데, 이때 정렬된 상태를 어떻게 유지할 것인지를 해결하는 문제이다.
배열 기반 구조에서 데이터 삽입/삭제 후 `sort()`로 전체 정렬을 유지하는 방법은 비효율적이다.
multiset 컨테이너를 이용하면 더 효율적으로 정렬 상태를 유지할 수 있다.
이유는, multiset은 이진 탐색 트리 구조이기 때문이다. 이는 이미 정렬된 상태의 데이터에 삽입/삭제/검색/수정 연산을 하더라도, 모두 $\mathbf{O(\;log\;N)}$ 시간복잡도로 수행할 수 있다는 뜻이다.
multiset을 이용한 풀이는 아래와 같다.
#include <iostream>
#include <set>
using namespace std;
int main() {
ios_base::sync_with_stdio(0);
cin.tie(0);
int T, k;
cin >> T;
for (int i = 0; i < T; i++) {
multiset<int> ms;
cin >> k;
for (int j = 0; j < k; j++) {
int n;
char op;
cin >> op >> n;
if (op == 'I') {
ms.insert(n);
}
else {
/* 비어있는 경우, 무시 */
if (ms.empty()) continue;
if (n == 1) {
ms.erase(prev(ms.end()));
}
else {
ms.erase(ms.begin());
}
}
}
if (ms.empty()) {
cout << "EMPTY\n" ;
}
else {
cout << *prev(ms.end()) << ' ' << *ms.begin() << '\n';
}
}
}
'🐸 Problem Solving > BOJ' 카테고리의 다른 글
[BOJ/C++] 백준 11047번: 동전 0 (0) | 2024.12.06 |
---|---|
[BOJ/C++] 백준 1920번: 수 찾기 (0) | 2024.11.28 |
[BOJ/C++] 백준 2178번: 미로 탐색 (0) | 2024.11.20 |
🔗 문제 링크 : https://www.acmicpc.net/problem/7662
💀 12%에서 틀렸습니다!
이 경우는 문제에서 새로운 테스트케이스가 시작되면서 Q를 깨끗하게 비워주지 않아서 생기는 문제일 확률이 높다.
본인도 Q로 사용할 컨테이너를 선언하는 위치를 테스트케이스 "시작 전" -> 테스트케이스 "시작" 부분으로 옮겨서 문제를 해결하였다.
문제
이중 우선순위 큐(dual priority queue)는 전형적인 우선순위 큐처럼 데이터를 삽입, 삭제할 수 있는 자료 구조이다. 전형적인 큐와의 차이점은 데이터를 삭제할 때 연산(operation) 명령에 따라 우선순위가 가장 높은 데이터 또는 가장 낮은 데이터 중 하나를 삭제하는 점이다. 이중 우선순위 큐를 위해선 두 가지 연산이 사용되는데, 하나는 데이터를 삽입하는 연산이고 다른 하나는 데이터를 삭제하는 연산이다. 데이터를 삭제하는 연산은 또 두 가지로 구분되는데 하나는 우선순위가 가장 높은 것을 삭제하기 위한 것이고 다른 하나는 우선순위가 가장 낮은 것을 삭제하기 위한 것이다.
정수만 저장하는 이중 우선순위 큐 Q가 있다고 가정하자. Q에 저장된 각 정수의 값 자체를 우선순위라고 간주하자.
Q에 적용될 일련의 연산이 주어질 때 이를 처리한 후 최종적으로 Q에 저장된 데이터 중 최댓값과 최솟값을 출력하는 프로그램을 작성하라.
입출력 예시
입력
입력 데이터는 표준입력을 사용한다. 입력은 T개의 테스트 데이터로 구성된다. 입력의 첫 번째 줄에는 입력 데이터의 수를 나타내는 정수 T가 주어진다. 각 테스트 데이터의 첫째 줄에는 Q에 적용할 연산의 개수를 나타내는 정수 k (k ≤ 1,000,000)가 주어진다. 이어지는 k 줄 각각엔 연산을 나타내는 문자(‘D’ 또는 ‘I’)와 정수 n이 주어진다. ‘I n’은 정수 n을 Q에 삽입하는 연산을 의미한다. 동일한 정수가 삽입될 수 있음을 참고하기 바란다. ‘D 1’는 Q에서 최댓값을 삭제하는 연산을 의미하며, ‘D -1’는 Q 에서 최솟값을 삭제하는 연산을 의미한다. 최댓값(최솟값)을 삭제하는 연산에서 최댓값(최솟값)이 둘 이상인 경우, 하나만 삭제됨을 유념하기 바란다.
만약 Q가 비어있는데 적용할 연산이 ‘D’라면 이 연산은 무시해도 좋다. Q에 저장될 모든 정수는 -231 이상 231 미만인 정수이다.
출력
출력은 표준출력을 사용한다. 각 테스트 데이터에 대해, 모든 연산을 처리한 후 Q에 남아 있는 값 중 최댓값과 최솟값을 출력하라. 두 값은 한 줄에 출력하되 하나의 공백으로 구분하라. 만약 Q가 비어있다면 ‘EMPTY’를 출력하라.

풀이
이중 우선순위 큐를 구현하는 문제이다.
테스트케이스에서 값을 삽입 및 삭제 기능을 수행하여야 하는데, 이때 정렬된 상태를 어떻게 유지할 것인지를 해결하는 문제이다.
배열 기반 구조에서 데이터 삽입/삭제 후 sort()
로 전체 정렬을 유지하는 방법은 비효율적이다.
multiset 컨테이너를 이용하면 더 효율적으로 정렬 상태를 유지할 수 있다.
이유는, multiset은 이진 탐색 트리 구조이기 때문이다. 이는 이미 정렬된 상태의 데이터에 삽입/삭제/검색/수정 연산을 하더라도, 모두 $\mathbf{O(\;log\;N)}$ 시간복잡도로 수행할 수 있다는 뜻이다.
multiset을 이용한 풀이는 아래와 같다.
#include <iostream> #include <set> using namespace std; int main() { ios_base::sync_with_stdio(0); cin.tie(0); int T, k; cin >> T; for (int i = 0; i < T; i++) { multiset<int> ms; cin >> k; for (int j = 0; j < k; j++) { int n; char op; cin >> op >> n; if (op == 'I') { ms.insert(n); } else { /* 비어있는 경우, 무시 */ if (ms.empty()) continue; if (n == 1) { ms.erase(prev(ms.end())); } else { ms.erase(ms.begin()); } } } if (ms.empty()) { cout << "EMPTY\n" ; } else { cout << *prev(ms.end()) << ' ' << *ms.begin() << '\n'; } } }
'🐸 Problem Solving > BOJ' 카테고리의 다른 글
[BOJ/C++] 백준 11047번: 동전 0 (0) | 2024.12.06 |
---|---|
[BOJ/C++] 백준 1920번: 수 찾기 (0) | 2024.11.28 |
[BOJ/C++] 백준 2178번: 미로 탐색 (0) | 2024.11.20 |