トヨタ自動車プログラミングコンテスト2023#7(AtCoder Beginner Contest 328) G問題メモ
G - Cut and Reorder
問題
- 長さ の数列を、以下の操作を好きに繰り返して から にする
- 操作1: 数列を好きな位置で切り刻んで好きな順で並べなおす。1箇所切り刻むのにコスト
- 操作2: 好きな を選んで、 に を加算する。コスト
- 最小コストを求めよ
- 実行制限時間 2.8秒
- メモリ制限 512MB
解法
オーダーに が含まれるbitDP解法なら、 よりもうちょっと少なく設定されるだろうから別の解法かな?と変なメタ読みしたが、普通にbitDPだった。 いつもと違うメモリ制限も、想定解法が に対して を落とすためらしい。
を以下で定義する。
- として、 を、 にするのにかかる最小コスト
配るDPで、 からの遷移を考える。
は決定しているので、次の から連続する、 操作1の結果のブロック1単位の切り出し方・移動先を全て試す。
S={2,3,6,7,8,9} 1 2 3 4 5 6 7 8 9 A o o o o o o - - - o:決定済み -:未決定 B - o o - - o o o o
- 長さ1のブロック は、 に移せる
- 長さ2のブロック は、 に移せる
- 長さ3のブロック は、この ではどこにも移せない
1ブロックの切り出しにつきコスト かかり、移した先では操作2によって各要素の差の絶対値だけのコストがかかる。
- 長さ のブロックで、それぞれ と が左端であるもの同士を、操作2だけで合わせるコスト
は で事前計算でき、これを使うと遷移は(切り出し方・移動先)1箇所につき となる。
をbitで表現して小さい方から計算していき、 が答えとなる。
計算量の考え方
1つの に対する(切り出し方・移動先)の総数を考えると、
一見、ブロックの長さ 、位置合わせ の に見える。
これだと、 は 通りあるので となり少し厳しい。
だが実際は、 が大きくなる毎にブロック長の上限は狭まっていくし、長いブロックは位置合わせの回数も少なく済む。
公式Editorialによると、ブロックの長さに着目することで、 長さ のブロックが試されるような は 、 またそこからの位置合わせも 箇所だけ試せばよいので、
- →
となるらしい。
公式のサンプルコードは の方から遷移先の を探索しているが、
以下の自分のコードは、 を基準にまず遷移の長さ を決めて、それを1つずつずらしている。
そのため少し遷移に無駄があって、どちらかというと を定数倍削減している感じだが、通った。
遷移回数も、 ほどある。