Official

D - Sequence Query Editorial by sugarrr


クエリを先読みしない方法について

multiset を用いて、クエリを順番に処理していきます。
multiset を \(S\) とします。

  • \(c_i = 1\) のとき
    \(S\)\(x\) を挿入( insert )すればよいです。

  • \(c_i = 2\) のとき
    S.upper_bound(x) によって \(x\) より大きい最初のイテレータを取得し、イテレータを \(k\) 回デクリメントすればよいです。

  • \(c_i = 3\) のとき
    S.lower_bound(x) によって \(x\) より小さくない最初のイテレータを取得し、イテレータを \(k-1\) 回インクリメントすればよいです。

\(c_i = 2,3\) において、イテレータが S.begin()S.end() を超えないように注意して実装しましょう。
全体の計算量は \(O(N \log N)\) です。


クエリを先読みする方法について

クエリを先読みして、\(x\) の値について座標圧縮しておきます。
以下、座標圧縮後の値を \(x'\) で表します。
Fenwick Tree または Segtree を用います。(以下解説ではFenwick Treeを用いたとします。)

  • \(c_i = 1\) のとき
    \(x'\)\(1\) 加算すればよいです。

  • \(c_i = 2\) のとき

    Fenwick Tree において \([m,x']\) の和が \(k\) 以上か?

    という問題において、\(m\) について二分探索すればよいです。
    なお、記号 \([a,b]\) は閉区間を意味しています。

  • \(c_i = 3\) のとき

    Fenwick Tree において \([x',m]\) の和が \(k\) 以上か?

    という問題において、\(m\) について二分探索すればよいです。

上記を素直に実装すると、全体の計算量は \(O(N \log^2 N)\) になります。
ACL の Segtree の max_rightmin_left 関数を用いて \(O(N \log N)\) にすることもできます。

posted:
last update: