Codeforces Round #521 (Div. 3)F2. Pictures with Kittens (hard version)
問題概要
長さ の整数列 が与えられる. この中からちょうど 個の整数を選択するが, その時少なくとも連続する 個の中の一つが選ばれてなければならない. この時, 選んだ整数の合計の最大値はいくらか.
制約
解法
dp をしましょう. ( 個の整数を, 番目までの整数で選び, かつ を選んだ時の合計の最大値 )と定義します. 通常の dp では添字が普通逆ですが, 逆だと後々困るのでこう定義しておきます.
遷移を考えます. 番目を選ぶ時, 一個前に選んだ整数は 個以内でなければなりませんから,
のような遷移式ができます. 最後に選ぶ整数は のいずれかですから, 答えは となります.
これを愚直に実装すると計算量は なので, これだと TLE します(F1 は通ります). なんとかして高速化しましょう.
dp の遷移式を見れば, についての添字は一つ前しか影響せず, についてはある範囲の最大値となっています. 典型的なテクニックですが, dp テーブルを SegmentTree として持つことにより区間最大値を高速に取得できるので, 一度の遷移が で済みます. この時の全体の計算量は です.
ただし, 添字 をあらわに持つと MLE します. in-place 化をすることで対処しましょう(一個先を作成して元の配列と swap することを繰り返すことでメモリを抑えるテクニックです).
さらに in-place 化してもなんか TLE します. 定数倍高速化のため, 更新する の範囲を限定すれば間に合わせることができます. 例えば, などは, 定義に合わせると 個の整数を 番目までで選ぶことに対応しているため, 明らかに値をとらず更新が不要です.
ACL のSegTree など高速な SegmentTree を用いないとどうやっても間に合わないかもしれません. 公式解説にはさらに を落とした方法が載っているので確かめてみてください.