状态表示:$f(i,j,0/1)$表示由前$i$个数字构成$j$个区间,且第$i$个数取或不取的最大值
状态转移:$f(i,j,0) = max(f(i-1,j,0),f(i-1,j,1))$,$f(i,j,1) = max(f(i-1,j,1),max(f(i-1,j-1,1),f(i-1,j-1,0))) + w[i]$
加亿点点优化就过了
#pragma GCC optimize("Ofast")
#include <bits/stdc++.h>
#define fi first
#define se second
#define max(a, b) (a > b ? a : b)
#define min(a, b) (a < b ? a : b)
using namespace std;
using i64 = long long;
constexpr int inf = 0x3f3f3f3f, N = 1E6 + 5;
int s[N];
i64 dp[2][1005][2];
void inline read(int& x) {
x = 0;
int f = 1;
char c = getchar();
while (c < '0' || c > '9') {
if (c == '-')f = -1;
c = getchar();
}
while (c >= '0' && c <= '9')
x = x * 10 + (c - '0'), c = getchar();
x *= f;
}
int main() {
int m, n;
while (~scanf("%d%d", &m, &n)) {
for (int i = 1; i <= n; i++)
read(s[i]);
memset(dp, -0x3f, sizeof dp);
dp[0][0][0] = 0;
for (int i = 1; i <= n; i++) {
int pre = i - 1 & 1, cur = i & 1;
dp[cur][0][0] = 0;
for (int j = 1; j <= min(i, m); j++) {
dp[cur][j][0] = max(dp[pre][j][1], dp[pre][j][0]);
dp[cur][j][1] = max(dp[pre][j][1], max(dp[pre][j - 1][0], dp[pre][j - 1][1])) + s[i];
}
}
printf("%lld\n", max(dp[n & 1][m][1], dp[n & 1][m][0]));
}
return 0;
}