题意:

解法:
首先令a[i]=a[i]-x.
那么题目中子区间的条件就变为子区间的和>=0了.
考虑对于一个区间,如何判断其任意子区间都满足条件.
假设a[l,i-1]满足条件,我们要添加a[i],
1.当a[i]+a[i-1]>=0满足时,我们可以将[i-1,i]组合到一起.
2.当a[i]+a[i-1]>=0以及a[i]+a[i-1]+a[i-2]>=0同时满足时,
我们可以将[l,i]组合到一起.
即只要加入a[i]之后,末尾长度为2和3的都满足,那么添加a[i]后的整个区间就满足.
第一个结论比较显然.
第二个结论是怎么来的呢?
考虑以i作为子区间右端点:
1.对于末尾长度=2,需要满足a[i]+a[i-1]>=0.
2.对于末尾长度=3,需要在1的基础上满足a[i]+a[i-1]+a[i-2]>=0.
3.对于末尾长度=4,需要在1和2的基础上满足a[i]+a[i-1]+a[i-2]+a[i-3]>=0,
由条件1可知a[i]+a[i-1]>=0, a[i-2]+a[i-3]>=0,
因此a[i]+a[i-1]+a[i-2]+a[i-3]>=0显然成立.
4.对于末尾长度=5,同理,a[i]+a[i-1]>=0成立,a[i-2]+a[i-3]+a[i-4]>=0也成立.
因此a[i]+a[i-1]+a[i-2]+a[i-3]+a[i-4]>=0成立.
即对于右端点为i,长度>3的子区间,可以将子区间拆分为长度为2或3的更小区间的组合,
来证明条件成立.
所以我们只需要判断新加入的a[i],和前面区间的末尾两个数是否满足条件即可.
令d[i][j]表示前i个数,末尾j个数被选中的最大答案.
其中j的取值范围为[0,2].
转移时,我们只需要判断a[i]和a[i-1],a[i-2]的和是否满足条件,
如果满足条件则可以转移.
Code:
#include <bits/stdc++.h>
using namespace std;
#define X first
#define Y second
#define int long long
#define PI pair<int, int>
const int maxm=2e6+5;
const int mod=998244353;
int n,x;
int a[maxm];
int d[maxm][4];
void solve(){
cin>>n;
for(int i=1;i<=n;i++)cin>>a[i];
cin>>x;
for(int i=1;i<=n;i++)a[i]-=x;
for(int i=0;i<=n;i++){
for(int j=0;j<=2;j++){
d[i][j]=-1e18;
}
}
d[0][0]=0;
for(int i=1;i<=n;i++){
int ok2=(i-1>=0)&&(a[i]+a[i-1]>=0);
int ok3=(i-2>=0)&&(a[i]+a[i-1]+a[i-2]>=0);
d[i][0]=max({d[i-1][0],d[i-1][1],d[i-1][2]});
d[i][1]=max(d[i][1],d[i-1][0]+1);
if(ok2){
d[i][2]=max(d[i][2],d[i-1][1]+1);
}
if(ok2&&ok3){
d[i][2]=max(d[i][2],d[i-1][2]+1);
}
}
int ans=max({d[n][0],d[n][1],d[n][2]});
cout<<ans<<endl;
}
signed main() {
#define MULTI_CASE
ios::sync_with_stdio(0);
cin.tie(0);
#ifndef ONLINE_JUDGE
freopen("../in.txt", "r", stdin);
freopen("../out.txt", "w", stdout);
#endif
#ifdef MULTI_CASE
int T;
cin >> T;
while (T--)
#endif
solve();
return 0;
}