프로그래머스에도 비슷한 문제가 있어서 그때는 파이썬으로 heapq 활용해서 간단하게 구현했었는데, 이번에는 C++로 풀었다. 파이썬에서 max(리스트) 기능이 얼마나 소중한거인지 깨달았다...
두개의 우선순위큐(min heap, max heap) 를 써야되는 것은 알고있었다. 그런데 시간초과가 문제였다.
처음에는 Delete할때마다 다른 큐에서도 pop하면서 찾아서 다시 넣어주고 그랬는데, 최악 케이스 N log(N)이라서 문제였나보다.
그래서 검색하던 도중 lazy update에 대해서 보게되었다. delete 해야할 것들을 따로 저장해주고, Delete때마다 pop()해서 나오는 힙에서 확인해주었다. qLen라는 것을 저장해두어 qLen이 0일때 발생하는 불필요한 동기화를 없애주었다.
// 반례 https://www.acmicpc.net/board/view/73633
#include <iostream>
#include <vector>
#include <queue>
#include <algorithm>
using namespace std;
typedef long long int lli;
int T;
int k;
int qLen=0;
priority_queue<int,vector<int>,greater<int>> minq;
priority_queue<int,vector<int>,greater<int>> minqTobeDel;
priority_queue<int,vector<int>,less<int>> maxq;
priority_queue<int,vector<int>,less<int>> maxqTobeDel;
void Input(){
cin >> k;
}
void removeMax(){
int val = maxq.top();
maxq.pop();
minqTobeDel.push(val);
}
void removeMin(){
int val = minq.top();
minq.pop();
maxqTobeDel.push(val);
}
void insertNum(int n){
maxq.push(n);
minq.push(n);
}
void clearQ(){
priority_queue<int,vector<int>,greater<int>> minqEmpty;
priority_queue<int,vector<int>,less<int>> maxqEmpty;
priority_queue<int,vector<int>,greater<int>> lazyMinEmpty;
priority_queue<int,vector<int>,less<int>> lazyMaxEmpty;
maxq.swap(maxqEmpty);
minq.swap(minqEmpty);
maxqTobeDel.swap(lazyMaxEmpty);
minqTobeDel.swap(lazyMinEmpty);
qLen=0;
}
void lazyUpdateMaxq(){
int val;
int maxCandidate;
while(!maxqTobeDel.empty()){
val = maxqTobeDel.top();
maxCandidate = maxq.top();
if(val > maxCandidate){
maxqTobeDel.pop();
}else if(val < maxCandidate){
return;
}else {
maxqTobeDel.pop();
maxq.pop();
}
}
}
void lazyUpdateMinq(){
int val;
int minCandidate;
while(!minqTobeDel.empty()){
val = minqTobeDel.top();
minCandidate = minq.top();
if(val < minCandidate){
minqTobeDel.pop();
}else if(val > minCandidate){
return;
} else {
minqTobeDel.pop();
minq.pop();
}
}
}
void Solve(){
char cmd;
int n;
for(int i=0; i<k; ++i){
cin >> cmd >> n;
//cout <<"=====" << cmd << " " << n << "\n";
switch(cmd){
case 'D':
if(qLen > 0){
if(n == 1) {
lazyUpdateMaxq();
removeMax();
//lazyUpdateMinq();
}else if(n== -1) {
lazyUpdateMinq();
removeMin();
//lazyUpdateMaxq();
}
qLen--;
} // empty : pass
break;
case 'I':
qLen++;
insertNum(n);
break;
}
}
if(qLen ==0) cout << "EMPTY\n";
else {
lazyUpdateMaxq();
lazyUpdateMinq();
cout << maxq.top() <<" " << minq.top() << "\n";
}
}
int main(){
ios::sync_with_stdio(false);
cin.tie(NULL);
cout.tie(NULL);
cin >> T;
for(int i=0; i<T; ++i){
clearQ();
Input();
//cout << "i : " << i << "\n";
Solve();
}
}
참고자료
https://kangwlgns.tistory.com/35
https://panty.run/pq-del-elem/
728x90
반응형
'프로그래밍 > 알고리즘(PS)' 카테고리의 다른 글
[백준][c++] 7662 이중 우선순위큐 (0) | 2021.12.13 |
---|---|
[프로그래머스][python] 이중우선순위큐 (0) | 2021.12.13 |
[프로그래머스][python] 주식 가격 (0) | 2021.12.06 |
[프로그래머스][python] 다리를 지나는 트럭 (0) | 2021.12.03 |
[프로그래머스][python] 프린터 (0) | 2021.12.03 |