白駿1655号-平凡なリュックサック
22040 ワード
問題を読み、簡単にアクセスすると、入力を受信するたびにソートし、中間値を検索して出力できます.私も、コードしやすい結果はタイムアウト...
中間値の並べ替えと検索をO(1)に設定する必要があることを認識した後,優先キューを用いて異なるデータ構造形式を考慮した.
これは、2つの優先キューを使用して入力した数値の中間値をtopに維持し、抽出する問題です.
最初に想定した方法は、優先順位キューを2つのキュー(最大スタック、最小スタック)に分けてソート状態を作成することです.
例:
入力した数字が1,2,3,4,5,6,7,8の場合
優先キュー1(最大ヒープ):4、3、2、および1
優先キュー2(minheap):5、6、7、8
として設定されたメソッド.
2つのレベルに分けられますが、優先キュー1を逆起動して、優先キュー2を反時計回りに表示すると、優先キュー1には常に中間値が1、2、3、4、5、6、7、8の順に表示されます.
論理はまず、最も大きな数の最初の数値入力を受け入れます.
minheap以上、max heap以下.
次に、max heapのtopに基づいて、新しく入力した数字をmax heapにプッシュするか、mean heapにプッシュします.
中間値が最も多くなるように、2つの優先キューの数を常に等しいか、または差が1に設定する必要があります.
優先キュー1(最大ヒープ):2 1
優先キュー2(minheap):34 5 6 8
上記の例に示すように、数を一方に偏らせてはいけません.入力した新しい数値がpushの数と同じである場合、一方の側にpushを入力し、pushキューのtopを別のキューに移動します.
2つのキューの数が異なる場合は、プッシュする前に同じキューに移動し、上記の操作を実行します.
2つの優先キューのバランスを実現し、中間値を維持します.
#include <iostream>
#include <vector>
#include <algorithm>
#include <queue>
using namespace std;
int main(){
ios_base::sync_with_stdio(false); cin.tie(NULL);
int num;
cin >> num;
priority_queue<int, vector<int>, greater<int> > min_queue;
priority_queue<int, vector<int>, less<int> > max_queue;
int input;
cin >> input;
max_queue.push(input);
cout << max_queue.top() << '\n';
for(int i = 1; i < num; i++){
cin >> input;
if(max_queue.top() < input){
if(max_queue.size() == min_queue.size()){
min_queue.push(input);
int temp = min_queue.top();
min_queue.pop();
max_queue.push(temp);
}
else{
min_queue.push(input);
if(max_queue.size() != min_queue.size()){
int temp = min_queue.top();
min_queue.pop();
max_queue.push(temp);
}
}
}
else{
if(max_queue.size() == min_queue.size()){
max_queue.push(input);
int temp = max_queue.top();
max_queue.pop();
min_queue.push(temp);
}
else{
max_queue.push(input);
if(max_queue.size() != min_queue.size()){
int temp = max_queue.top();
max_queue.pop();
min_queue.push(temp);
}
}
}
if(max_queue.size() < min_queue.size()){
cout << min_queue.top() << '\n';
}
else{
cout << max_queue.top() << '\n';
}
}
}
他の人のコードリファレンス
他人のコードを見て勉強するとき、私の論理より簡単な論理があります.私が実施するとき、pushはmax heapのtopと比較して優先順位キューを選択してpushを行い、これは不要なプロセスです.最大スタックと最小スタックの数が同じである場合、最大スタックにプッシュすることによって、数が異なる場合に最小スタックにプッシュすることによって、常に2つのキューの数が同じに保たれる.△この部分は私と同じです.ただし、プッシュするキューではなく入力数のサイズを比較し、プッシュ後に2つのキューのtopを比較することで、常にmax heapのtopに小さい値を入力することができます.これは、優先順位キューにプッシュし、topを比較してmax heapに小さな値を移動するだけで、最終的な形式は私の論理と同じになります.これらの論理の条件文は、より少なく、より簡単で、より直感的だと思います.
#include <iostream>
#include <queue>
using namespace std;
int main(){
ios_base::sync_with_stdio(false); cin.tie(NULL);
priority_queue<int , vector<int>, greater<int> > min_queue;
priority_queue<int, vector<int>, less<int> > max_queue;
int num;
cin >> num;
for(int i = 0; i < num; i++){
int input;
cin >> input;
if(max_queue.size() == min_queue.size()){
max_queue.push(input);
}
else{
min_queue.push(input);
}
// 두 우선순위 큐가 비어있지 않으면서 max heap의 top가 min heap의 top 보다 클 경우 swap
if(!max_queue.empty() && !min_queue.empty() && max_queue.top() > min_queue.top()){
int swap_temp1 = max_queue.top();
int swap_temp2 = min_queue.top();
max_queue.pop();
min_queue.pop();
max_queue.push(swap_temp2);
min_queue.push(swap_temp1);
}
cout << max_queue.top() << '\n';
}
}
リファレンス
https://blog.naver.com/music4537/222249608344
その他
前述したように、I/Oが頻繁にn回発生する場合、endまたはcinおよびcoutを使用するとタイムアウトが発生する可能性が高い.
ios_base::sync_with_stdio(false); cin.tie(NULL);
上記の処理をドメイン内で実行することにより、I/O速度を向上させることができる.また、endではなく「n」を使用して改行を高速化します.
Reference
この問題について(白駿1655号-平凡なリュックサック), 我々は、より多くの情報をここで見つけました https://velog.io/@bbak_joon/백준-12865번-평범한-배낭テキストは自由に共有またはコピーできます。ただし、このドキュメントのURLは参考URLとして残しておいてください。
Collection and Share based on the CC Protocol