M-SOLUTIONS プロコンオープン 2020 F - Air Safety
問題
格子状の点上に配置された飛行機が4方向のうち決められたほうに飛ぶとき、衝突するか判定する。 衝突する場合は、その中で最も早い衝突が何秒後に起こるか求める。
考察
衝突には正面衝突と直行する衝突の2種類があるので、それぞれの解の最小値が答えになる。
正面衝突
方向に向かう飛行機と方向に向かう飛行機が衝突を起こす条件は、明らかにで、衝突までの時間は秒。
の判定には二分探索を用いる。実装にc++のsetを使えばupper_boundを用いる。
方向も同様。
直行する衝突
方向に向かう飛行機とx方向に向かう飛行機の衝突を考える。
方向に向かう飛行機が衝突する点と秒数の組み合わせはの点。 方向に向かう飛行機がにあるなら、初期値はであることがわかる。 よって、半直線上にある方向に向かう飛行機はあるか判定すればよいことがわかる。 衝突までの時間は秒。
の判定も二分探索。
あとの組み合わせは回転で同じ問題になる。
実装
第三回 アルゴリズム実技検定 N - 入れ替えと並び替え
問題
長さの数列に、以下の合計個のクエリを実行した結果を求める。
- とをスワップ
- を昇順に並び替える
考察
1つ目のクエリはで実行可能なので、2つ目のクエリを高速に行う方法を考える。
数列の転倒数は、1つ目のクエリでは1増減し、2つ目のクエリでは発生するスワップの回数分だけ減少することがわかる。 よって、全ての2つ目のクエリで発生するスワップの合計は高々回であることがわかった。 また、2つ目のクエリではとなる箇所でスワップされるので、このようなの集合を知っておく必要がありそう。
1つ目のクエリでとをスワップすることを考える。 かどうかの関係が変わる可能性があるのは、の3箇所なので、これらの関係がか判定し、を更新する。
2つ目のクエリで昇順にソートすることを考える。 なるがあるとき、を更新し、の関係を元にを更新する。
setのデータ構造を用いると、上記の処理がで十分高速に実行可能である。