2019年8月13日火曜日

ARC 060 E - 高橋君とホテル

ARC 060 E - 高橋君とホテル

R[k][x]:=R[k][x] := ホテルxxから2k2^k日以内にたどり着けるもっとも右のホテル

というテーブルを作ってクエリに答えればいいのだが、ダブリングの実装でいつももたついているのでメモしておく。

RRのサイズについて。制約より、高々10510^5日でどの地点からどの地点にも移動できるので、テーブルは2d<1052^d < 10^5であるような最大のddまで作ってあれば十分である。この場合はlog2105=16\lfloor \log_2 10^5 \rfloor = 16、ただし、20=12^0 = 1日のデータも必要なので、RRのサイズとしては1717になる。計算が面倒or不安なら多めに取っても問題ない。

更新について。k=0k = 0のデータだけ二分探索等で作れば、k=1,...,16k = 1, ..., 16についてはR[k][x]:=R[k1][R[k1][x]]R[k][x] := R[k-1][R[k-1][x]]で得られる。

クエリについて。クエリ(a,b)(a<b)(a, b) (a< b)を処理する時は、R[16][x],R[15][x],...,R[0][x]R[16][x], R[15][x], ..., R[0][x]の順でbbにたどり着かないように採用していって、最後に1を足すのが一番簡単そう。疑似コードで書くと、

sum := 0
for k from 16 downto 0
    if R[k][a] < b
        sum += 2^k
        a := R[k][a]
return sum + 1

最初、なぜか非対称だと思って右に行く場合のテーブルと左に行く場合のテーブルを作ってしまった。