問題はこちら
問題概要
与えられた長さの数列を長さ以下の個の連続部分数列に分解する. 数列のスコアをその数列の要素の和の絶対値とするとき, スコアの和の最大値を求めよ.思考の流れ
問題とか制約とかから明らかにDPっぽい.すぐ思いつくのは 「前から番目まででちょうど個に分解したものの最大値」となる.
以下に細かい条件を無視した遷移の式を書く.
以上から, の和を求める部分を累積和を用いたとしても一回の遷移でかかるので全体でかかって間に合わない.
とする. また, であることを考えると, 上記の遷移式は以下のようにかける.
となるのでとが高速に計算できればいい.
区間maxなので番目の要素にをもつSegmentTreeと番目の要素にをもつSegmentTreeを持っておけばいい.のループを一番外側に書けばSegmentTreeを使い回せるので楽. 時間計算量は
公式解説にはmax区間の右端と左端の幅が固定(=右端と左端が広義単調増加)なのを利用してDequeを使った実装を行なっている(スライド最小値とも呼ばれている. 詳しくは蟻本). これをすると時間計算量がとなる. SegmentTreeの解法はC++でもかなりギリギリだったので普通はこっちを使ったほうがいい. Dequeの方は実装も難しくないが, SegmentTreeは脳死で貼るだけなのでこっちを使った.