説明
Mo’s algorithm - ei1333の日記
クエリを先読みできて、区間の伸縮が簡単に計算できるとき Mo’s Algorithm が適用できる可能でいがある。
計算量
区間を伸縮するときの計算量を $f(N)$ とする
実装例
- Mo($N$, $Q$):= 区間の長さ $N$, $Q$ 個のクエリで初期化する。
- add($l$, $r$):= クエリ $[l, r)$ を追加する。
- run($add$, $del$, $rem$):= 全てのクエリを処理する。ここで, add(idx) は idx 番目の要素を入れる, del(idx) は idx 番目の要素を消す, rem(idx) はクエリ idx を処理する関数。
検証
SPOJ D-Query
SPOJ Frequent values
応用 1: ロールバック平方分割
普通のMoだと要素を削除する操作が要求された。
Mo’s algorithm の上位互換の話 - あなたは嘘つきですかと聞かれたら「YES」と答えるブログ をすると、削除操作は不要で要素の追加と snapshot を撮った位置まで巻き戻す rollback ができればよい。
- MoRollBack($N$, $Q$):= 区間の長さ $N$, $Q$ 個のクエリで初期化する。
- add($l$, $r$):= クエリ $[l, r)$ を追加する。
- run($add$, $rem$, $reset$, $snapshot$, $rollback$):= 全てのクエリを処理する。ここで, add(idx) は idx 番目の要素を入れる, rem(idx) はクエリ idx を処理する、$reset$ はデータ構造の初期化, $snapshot$ は現在の状態を記録, $rollback$ は $snapshot$ まで巻き戻す関数。
Codeforces
2014-2015 ACM-ICPC, NEERC, Southern Subregional Contest A - Nasta Rabbara
区間 $[l_i, r_i]$ の辺のみがあるときに、二部グラフかどうか答えよ