AGC032-D:Rotation Sort
やっぱりAGCの問題は綺麗で良いなあ...。
解法
Rotation操作はややこしいので、言い換えを考える。よく眺めると、右シフトは「好きな数を今の位置より右側の好きな位置に移す」と言い換えられる。左シフトも同様なので、結局
- 「コストを払い、好きな数を今の位置より右側の好きな位置に移す」
- 「コストを払い、好きな数を今の位置より左側の好きな位置に移す」
とい2つの操作を考えればよい。この操作ができるとき、ソートに必要なコストの最小値を求めることが求められている。
さて、sortするのに必要な最小コスト(または操作回数)を求める場合、dpを考えると有効な場合がある。特に、小さい数字からどの(相対的な)位置に置くか?ということを決めていくdpを考えるとうまくいきそうな気がしてくる。例えば、までは昇順に並んでいるとすれば、をどの位置に置くべきかはとの位置関係だけを見れば十分になるというのは都合が良いだろう。従って、dpの状態として「からまでは昇順に並んでいる」ということを持つことにする。もちろんこれだけでは不十分である。なぜ不十分かというと、より大きい数も含めたときに、全体としてどれくらい揃っているかということも重要だからである。ここでどういう情報を持つとよいかは難しいが、筆者は「より手前の位置にあって、より大きい数が個ある」という情報を持った。まとめると
- :からまでの数は昇順に並んでいて、より左側にあってより大きい数が個あるような順列にするときの、操作コストの最小値」
としてdpを行うことにした。
遷移を考えよう。まず、各数に行う操作は「左に動かす」「右に動かす」「動かさない」でいずれかを回のみでよいのは明らかだろう。さらに、dpの遷移の際にはまでは昇順に並んでいるとしているので、以下のように考えてよい。
- がより左側にあるときにに行う操作は「左に動かす」か「動かさない」
- がより右側にあるときにに行う操作は「右に動かす」
つまり、との位置関係が管理できれば遷移が可能になる。そこで、:元の順列に関して、より左側にありより大きい数の個数 とする。すると、からへの遷移について、のときはに該当し、そうでないときはに該当することがわかる。よって、以下のような遷移式が書ける。
初期値はで他は、答えはとなる。
実装
Submission #6232045 - AtCoder Grand Contest 032
実装はこの問題に取り組むレベルの人なら特に難しいところはないはず。