我们发现k{k}可以是答案的前提是线段的长度总和不超过n{n}。即k(k+1)2n\frac{k*(k+1)}{2}\le nk447k\le 447

dpi,jdp_{i,j}表示长度为jj的段的最大和,同时我们已经考虑了后缀ii上所有的元素,并且选择了长度为j,j1,...,1{j,j-1,...,1}的段,其中段的总和增加。

1.我们可以在长度为j{j}的段中包含元数i{i}

dp[i][j]=dp[i+1][j]

2.或者包含元素i{i},前提是dpi+j,j1dp_{i+j,j-1}的值大于段i,i+1,...i+j1{i,i+1,...i+j-1}上的总和。

dp[i][j]=max(dp[i+1][j],sum[i+j-1]-sum[i-1])

code:

#include <bits/stdc++.h>
#define ll long long
using namespace std;
const int maxn=1e5+7,inf=1e9+7;
int n,a[maxn],dp[maxn][450];
ll sum[maxn];
inline void solve() {
	cin>>n;
	for(int i=1;i<=n;++i) {
		cin>>a[i];
		sum[i]=sum[i-1]+a[i];
	}
	int k(0);
	while(k*(k+1)/2<=n) ++k;
	for(int i=1;i<k;++i) dp[n+1][i]=-inf;
	dp[n+1][0]=inf;
	for(int i=n;i;--i) {
		for(int j=0;j<k;++j) {
			dp[i][j]=dp[i+1][j];
			if( j && i+j-1<=n && sum[i+j-1]-sum[i-1]<dp[i+j][j-1] ) {
				dp[i][j]=max(dp[i][j],(int)(sum[i+j-1]-sum[i-1]));
			}
		}
	}
	int ans(0);
	for(int i=1;i<k;++i) if(dp[1][i]>0) ans=i;
	cout<<ans<<'\n';
}
int main() {
	cin.sync_with_stdio(false), cin.tie(nullptr),cout.tie(nullptr);
	int _;
	cin>>_;
	while(_--) solve();
	return 0;
}