ほぼ数学科の大学生の備忘録。

数学/物理の話をしていく…つもりだった……

ABC108D

本日はAtCoderのお話.
暇なときに過去問を埋めていて,そのときにかなり詰まった問題があったので自戒を込めて解説してみる.

問題は,こちら:
atcoder.jp

ABCのほかにARCでも使われたっぽいですね.
2年弱前の問題.

 L \leq 10^6 \leq 2^{20}であることを考えると, Lの二進展開っぽいことをすればよいというのまでは想像がついたが…

自分が通した解法

最初は二進展開っぽいことを二分木でやってみようとしたが普通に頂点

数が 20を超えた.そりゃそうだ.
他に良い手が思いつかなかったので,解説を眺めることに.
一直線のグラフを作って少しずつ調整するっぽいな,ということだけ認識してそこから自力でやってみることにした.

ここでかなり苦労したのだが,結果的に通せた解法を紹介してみる.

 L 2冪の場合は簡単で,例えば L=3の場合には図のようにすればよい.

 2冪でない場合が問題でである.
考察として,各点までで打ち切った場合に,どの長さのパスまで存在するかを書いてみる(半開区間で書いてあることに注意).

f:id:prfm_mkr:20200606174107p:plain

最終的に,一番右下を [0, L) にできればよいわけだ.
 r番目のノードまで,この図の形でグラフを作るとすると,  [0, 2^r-1)までは何も手を加えなくても実現できていることが分かる.

そのため,まずは  2^{r-1} \leq L を満たす最大の  r を求める.
現状ではこんな感じ.
f:id:prfm_mkr:20200606180213p:plain

 [0, 2^{r-1})については良いことにすると,残るは  [2^{r-1}, L) である.
どこかに辺を足すことで残りの部分について対応していきたいが,各点までのパスの長さが  0 から始まっていることを考えるとどこかに  2^{r-1}の長さの辺を足すのが妥当そうである.

例えば, r-1のノードからrのノードへと長さ  2^{r-1}の辺を足すことにすると,新たに  [2^{r-1}, 2^{r-1} + 2^{r-2}) の長さのパスが増えることになる.
これは,  2^{r-1} + 2^{r-2} \leq L のときは追加してよいが,そうでない場合は過剰にパスが増えてしまう.
従って,この判定を繰り返すことで徐々に残りの区間が減っていき,正しく解答できる.

f:id:prfm_mkr:20200606180035p:plain

イメージとしてはこんな感じです.