题目链接:https://codeforces.com/contest/1582/problem/E
k的最大值不超过500,所以有O(nk)是可以接收的复杂度。
令dp[i][j]为后缀i序列中,长度为j的序列和的最大值。
pre[i + j - 1] - pre[i - 1] < dp[i + j][j - 1],在满足这个条件的前提下,从dp[i+1][j]向dp[i][j]转移,则能保证,dp[i][j]的值是不覆盖dp[i + j][j - 1]的,所以可以满足序列长度依次为j, j - 1, … , 1的最优情况。
#include <bits/stdc++.h>
using namespace std;
using ll = long long;
const int INF = 0x3f3f3f3f;
const int N = 1e5 + 5;
const int K = 450;
int t, n;
ll a[N], pre[N], dp[N][K];
int main(void) {
// freopen("in.txt", "r", stdin);
scanf("%d", &t);
while (t--) {
scanf("%d", &n);
for (int i = 1; i <= n; i++) {
scanf("%lld", &a[i]);
pre[i] = pre[i - 1] + a[i];
}
int k = 0;
while (k * (k + 1) / 2 <= n) k++;
for (int j = 0; j < k; j++) dp[n + 1][j] = -INF;
dp[n + 1][0] = INF;
for (int i = n; i >= 1; i--) {
for (int j = 0; j < k; j++) {
dp[i][j] = dp[i + 1][j];
if (j && i + j - 1 <= n && pre[i + j - 1] - pre[i - 1] < dp[i + j][j - 1]) {
dp[i][j] = max(dp[i][j], pre[i + j - 1] - pre[i - 1]);
}
}
}
int ans = 0;
for (int j = 0; j < k; j++)
if (dp[1][j] > 0) ans = j;
printf("%d\n", ans);
}
return 0;
}