Educational Codeforces Round 87 D – Multiset を解いた記録

二分探索付き Fenwick Tree の動作チェックも兼ねて解いた問題

問題の概要

\(n\)個の整数からなる多重集合がある.\(q\)個のクエリを処理せよ.クエリの内容は以下の通り.

  • 整数\(k\)を多重集合に追加する
  • \(k\)番目に小さい数※を探し出し,削除する

※多重集合に属する全要素を昇順に並べ替えたときの\(k\)番目の要素.例えば \(\{1, 1, 2, 3, 5\}\) で「3番目に小さい数」は2である.

問題へのリンク

制約

  • \(1 \leq n, q \leq 10^6\)
  • \(1 \leq a_{i} \leq n-1\)
  • 多重集合に属する整数は\(1\)以上\(n\)以下
  • 削除クエリが飛んでくるとき,「\(k\)番目に小さい数」は必ず存在する
  • 入力はすべて整数

解法

二分探索付き Fenwick Tree(Binary Indexed Tree) があればやるだけです.配列の\(i\)番目の要素に「\(i\)が何個あるか?」の情報を持たせます.

  • \(k\)を追加:ft.add(k, 1)
  • \(k\)を削除:ft.add(k, -1)
  • \(k\)番目の要素を探す:ft.sum(x) >= k となるような最小のxを二分探索で探す

実装例

実行時間制限がキツイので,cin/coutを使う場合に入出力を高速化する呪文を使いました.