ABC179D
https://gyazo.com/7b170df6b0f48886ab9a41790797f20e
https://gyazo.com/39b5c5d2890f126f81169312eb00f3b3
しばらく悩んで、飛ばしてEへ
悩み「え、これ範囲が広いと困るのでは?」←正しい
でもそのコードを見て「あ、要するにこの最内ループを潰せばいいんだな」と気づく
少し綺麗にしたコード
code:python
def solve(N, K, SS):
for pos in range(1, N):
ret = 0
for left, right in SS:
start = pos - right - 1
end = pos - left
ret %= MOD
return ret % MOD
Twitter見てたら「いもす法だ」とか言ってる人がいたけど、そうかな。僕はそういう意識はなかった。 DPの計算をする上で範囲の和を計算する部分が、範囲が広い時に「たくさんの数を足し合わせる」になって遅いのが解決すべき問題
そこで「今までに計算した数の和」の配列を別途作ってやる
これは「新しい値を前の値に足す」で作れる
いざ広い範囲の和が必要になった時には、範囲終了点での累積和から範囲開始点の一つ手前の累積和を引けば得られる
https://gyazo.com/7b170df6b0f48886ab9a41790797f20e
セグメント木は範囲和がO(logN)なので、ループで回して和を計算するO(N)よりは速くなる
今回使った累積和はO(1)なのでさらに速い
累積和は先頭からしか値を入れられないが、セグメント木では任意の位置に入れられる。この柔軟性の分だけ遅いと言えるだろう。
今回は先頭からDPするので任意位置に入れられる必要はなかった。