イベントソート
概要
半開区間の集合が与えられます。区間ごとに値が与えられているとします。これらの区間は重なっていることもあります。
このとき、以下のクエリが与えられます。 地点の位置に定義されているの最小値(または最大値)を答えてください。
考え方
ABC128-Eの例を考えます。

図としてはこのようになっており、それぞれのクエリの最小値を求める必要があります。 このとき、についての集合を考えます。そして、左端の部分をのへの挿入、右端の部分をのからの削除というイベントとしてとらえます。また、クエリはクエリというイベントとして処理してみます。
このとき、
- 挿入イベント
- 削除イベント
- クエリイベント
というイベントがあることになります。これらのイベントを場所順に処理していきます。挿入イベントと削除イベントは順不同ですが、クエリイベントは同じ場所の挿入・削除終了後に処理される必要があります。
ABC128の例を処理してみると以下のようになることがわかります。

こうすると、場所における範囲の持つ値は、集合に入っている値になります。なので、クエリイベントでは、集合の最小値がその場所における答え、ということになります。Indexを用意しておくと、答えの配列に直接最小値を書き込めます。
上の例では複数回同じ値が集合に挿入されませんでしたが、実際には複数回の挿入があり得ます。そこで、集合を扱うためのデータ構造としては、multisetを使う必要があります。
実装 in Rust
multiset
Rustではmultisetはないので自分で実装する必要があるようです。
BtreeMapを使えば比較的簡単に順序付きmultisetもどきを実装できます。keyとして集合として扱いたい値を持ち、valueとしてカウントを持ちます。カウントが0になれば、keyを削除します。
enumにおけるPartialOrd
Actionはenumとして定義できると嬉しいです。RustのenumにPartialOrdをderiveすると、上から順番に大きいと判断されます。