题目

Shirotsume 来到了回转寿司店。从现在开始,Shirotsume 所在的柜台会依次放上N盘寿司。第 i 盘出现的寿司的美味度为 Ai

Shirotsume 决定拿起自己喜欢的寿司吃,但也考虑到其他客人的感受,决定不拿连续的 K 盘 及 K 盘以上的寿司。

请求出 Shirotsume 所吃的寿司的美味值的总和的最大值。

限制:

  • 2KN2×105
  • 1Ai109

算法分析

原题等价于求 Shirotsume 不吃的寿司的美味值总和的最小值 S。那么,答案就是所有寿司的美味值总和减去 S

dp[i] 表示在前 i 个寿司中,决定不吃第 i 个寿司时,不吃的寿司的美味值总和的最小值

由于不能吃连续的超过 K1 盘的寿司,所以转移方程为

dp[i]=minj=iKi1dp[j]+Ai

暴力的时间复杂度为 O(NK),可以用线段树将转移复杂度降为 O(logN)

代码实现
#include <bits/stdc++.h>
#if __has_include(<atcoder/all>)
#include <atcoder/all>
using namespace atcoder;
#endif
#define rep(i, n) for (int i = 0; i < (n); ++i)
using namespace std;
using ll = long long;
ll op(ll a, ll b) { return min(a, b); }
ll e() { return 1e18; }
int main() {
int n, k;
cin >> n >> k;
vector<int> a(n);
rep(i, n) cin >> a[i];
ll ans = 0;
rep(i, n) ans += a[i];
segtree<ll, op, e> t(n);
rep(i, k) t.set(i, a[i]);
for (int i = k; i < n; ++i) {
ll now = t.prod(i-k, i)+a[i];
t.set(i, now);
}
ans -= t.prod(n-k, n);
cout << ans << '\n';
return 0;
}