次のような動的計画法を考えます.
時刻 i における体力 j のときの得られる賞金の合計の最大をdp[i][j] としたとき,遷移は
- モンスターを討伐する: dp[i+1][j−1]=max(dp[i][j−1],dp[i][j]+Ai)(j=0)
- 休憩する: dp[i+1][M]=max(dp[i+1][M],dp[i][j])
- 何もしない: dp[i+1][j]=max(dp[i+1][j],dp[i][j])
となり,答えは 0≤j≤Mmaxdp[N+1][j] となります.
しかしこの動的計画法の時間計算量は O(NM) と間に合いません.
また「何もしない」を選ぶとき「休憩する」を選べば良いため,「何もしない」は選ばなくても良いことが分かります.
これをいわゆる貰いdpに変換すると
- モンスターを討伐する: dp[i][j]=dp[i−1][j+1]+Ai(j=M)
- 休憩する: dp[i][M]=0≤j≤Mmaxdp[i−1][j]
になります.
ここで時刻 i に「休憩する」をしたときの得られなかった賞金の合計の最小を dp′[i] としたとき, dp[i][j]=∑k=1iAk−dp′[i−j] より, dp′[i] の遷移は
- 休憩する: dp′[i]={00≤j≤Mmindp′[i−j−1]+Aiifi≤0if1≤i≤N
となり,答えは ∑i=1NAi−0≤i≤Mmindp′[N−i] となります.
Bi={i−j−1∣0≤j≤M} としたとき Bi=(Bi−1∖{i−M−2})∪{i−1} であるため,multiset
等を用いることにより b∈Bimindp′[b] を O(logM) で求めることができます.
よって時間計算量 O((N+M)logM) となり間に合います.
また,遅延セグメント木を用いてインラインDPをすることでも解くことが可能です.
想定ソースコード