题解:先将整个数组翻转,然后令dp[i][j]状态表示为表示从前i个数里面选,且选了j段数,属性为最后一段数的sum的最大值。然后根据最后一段的数的最后一个是否是第i个数进行状态转移。
详见代码。
AC代码:
#include <bits/stdc++.h>
#define int long long
using namespace std;
typedef long long ll;
const int N=1e5+5,M=505;
int n;
int a[N];
int sum[N];
int dp[N][M];
void solve(){
cin>>n;
for(int i=1;i<=n;i++)cin>>a[i];
reverse(a+1,a+1+n);
for(int i=0;i<=n;i++)
for(int j=0;j<=500;j++)
dp[i][j]=0,dp[i][1]=a[i];
for(int i=1;i<=n;i++)sum[i]=sum[i-1]+a[i];
int res=1;
for(int i=1;i<=n;i++){
for(int j=1;j<=500&&j<=i;j++){
dp[i][j]=max(dp[i][j],dp[i-1][j]);
int s=sum[i]-sum[i-j];
//cout<<s<<"&&&&"<<dp[i-1][j-1]<<endl;
if(s<dp[i-j][j-1]){
dp[i][j]=max(dp[i][j],s);
res=max(res,j);
}
}
}
cout<<res<<endl;
}
main(){
int T;
cin>>T;
while(T--)solve();
}```