Australia

ウォンバットのブログ

CODE FESTIVAL 2018 qual A D - 通勤

これを通せたおかげで予選通過できました。嬉しい。

解法

 X_0=0とします。DPをします。

 dp[i][j]:=ガソリンスタンド iまで来るにあたって、ガソリンスタンド jで最後に補給するとしたときの、そこまでのガソリンスタンドを書店に建て替えるパターン数

次の3つを考える必要があります。

  • 近くのガソリンスタンド jで補給をしていてガソリンスタンド iで補給ができないとき、ガソリンスタンド iを書店に建て替えても建て替えなくても変わらない
  • やや遠くのガソリンスタンド jで補給をしていてガソリンスタンド iで補給ができるとき、ガソリンスタンド iを書店に建て替えるなら最後に補給した場所は変わらず、建て替えないなら最後に補給したガソリンスタンドは iになる
  • めっちゃ遠いガソリンスタンド jで補給をしていてガソリンスタンド iまでたどり着けないとき、ガソリンスタンド jまでの情報は無意味になる

まとめると、次のようになります。

  dp[i][j]= \begin{cases}
    \displaystyle \sum_{F - T< X_i-X_{j'} \leq F} dp[i-1][j'] & (i=j) \\ 
    2dp[i-1][j] & (0 < X_i-X_j \leq F - T)\\
    dp[i-1][j] & (F - T< X_i-X_j \leq F)
  \end{cases}

これを愚直に処理すると O(N^2)となりTLEします。データを使いまわしてオーダーを落とすことを考えましょう。
列の末尾 n項を 2倍し、その前の m項の区間和を末尾に追加するという操作ができればいいわけです。
さらに、項は「 2区間」→「区間区間」→「無意味な区間」と移動する事を利用し、それぞれの区間をqueueで持ち、区間和も持っておけば、遷移が高速化できます。要は尺取法なので、全体の計算量は O(N)となります。

反省

ARC070 Eでやったのと似たようなDPの高速化でした。勉強の成果が出せてよかったです。
この回のC問題と同じく、方針はすんなり立てられたように思います。DPは得意分野にしていきたいです。
そして何より


精進します!