競技プログラミング日記

主に AtCoder の記事です

AtCoder Beginner Contest 217E

ABC217E

ソートの部分を速く済ませるのが課題. 毎回ソートするのではなく,必要な部分だけソートして, そうでないときはソートを保留しておきたい.
priority queue を用いると, 各元を追加したときに同時にソートされた形になる. 追加に \(O(log(size(que)))\) がかかる.

実装:
\(b\) を priority queue, \(a\) を queue とする. 組 \( (b,a) \) を,vector \(b * a\) と同一視する. ここで,\(b * a\) は \(b\) の元の後ろに \(a\) の元を並べた vector. もちろん,実装は ( (b,a) ) で行って,vector \(b*a\) は 実装には現れない.
とりあえず \(a\) の方に入れてソートを保留しておき, 必要な場面が来たときだけ \(b\) に入れてソートする.
出力クエリが来たら,\(b\) の先頭から取り出す. \(b\) が空のときは \(a\) の先頭から取り出す. 制約から,出力クエリのときに \(b,a\) のどちらかは空でない.

使っている記号,マクロ等 "https://ecsmtlir.hatenablog.com/entry/2022/12/23/131925"

int main() {
  ll q; cin >> q;


  queue<ll> a;
  min_priority_queue<ll> b;
  // b*a


  rep(qi,q){
    ll t; cin >> t;
    ll x;
    if(t == 1){
      cin >> x;
      a.push(x);
    }
    else if(t == 2){
      if(b.size()){
        cout << b.top() << endl;
        b.pop();
      }else{
        assert(a.size());
        cout << a.front() << endl;
        a.pop();
      }
    }else {
      while(a.size()){
        ll x = a.front(); a.pop();
        b.push(x);
      }
    }
  }


  return 0;
}