题意
给定 a 1 , a 2 , ⋯ , a n a_1, a_2, \cdots, a_n a1,a2,⋯,an 共 n n n 个数,以及一个整数 x x x 。
要在数组中选择尽量多的数,使得原数组任意一个长度大于 1 的子数组满足以下条件之一
- 至少有一个元素没有被选择
- a l , a l + 1 , ⋯ , a r ≥ x ∗ ( r − l + 1 ) a_l, a_{l+1}, \cdots , a_r \geq x * (r-l+1) al,al+1,⋯,ar≥x∗(r−l+1)
思路
观察条件 a l , a l + 1 , ⋯ , a r ≥ x ∗ ( r − l + 1 ) a_l, a_{l+1}, \cdots , a_r \geq x * (r-l+1) al,al+1,⋯,ar≥x∗(r−l+1) ,也就是说选中的元素平均值要大于 x x x 。大于等于 x x x 的元素对平均值有正的贡献,小于 x x x 的元素对平均值有负的贡献。不妨记大于等于 x x x 的元素为A,小于 x x x 的元素为B。由于相邻两个元素的平均值不能小于 x x x ,所以不可能存在BB相连的情况,B只可能单独存在或依附于A。只需要考虑B、AB、BA、BAB这四种形式即可。
从前往后枚举每一个元素,对于第 i i i 个元素贪心地进行选择:
如果第
i
−
1
i−1
i−1个元素未选,则当前为元素为孤立的,可以选择。
如果第
i
−
1
i−1
i−1个元素已选,第
i
−
2
i−2
i−2个元素未选,则需要考虑当前元素与前一个元素的平均值进行选择。
如果第
i
−
1
i−1
i−1个元素与第
i
−
2
i−2
i−2 个元素均已选,则需要考虑这三个元素的平均值与后两个元素的平均值进行选择。
代码
#include <iostream>
#include <vector>
#include <cstring>
using namespace std;
const int maxn = 1e5+10;
int num[maxn];
int dp[maxn];
signed main() {
#ifdef LOCAL
freopen("input.txt", "r", stdin);
freopen("output.txt", "w", stdout);
#endif
int t; cin >> t;
while(t--){
memset(num, 0, sizeof num);
memset(dp, 0, sizeof dp);
int n; cin >> n;
for(int i = 1 ; i<=n; i++){
cin >> num[i];
}
int x; cin >> x;
int ans = 0;
dp[1] = 1;
ans ++;
for(int i = 2; i<=n; i++){
if(!dp[i-1]) dp[i] = 1, ans++;
else if(dp[i-1] && !dp[i-2]){
if(num[i] + num[i-1] >= 2*x) dp[i] = 1, ans++;
}else if(dp[i-1] && dp[i-2]){
if(num[i] + num[i-1] + num[i-2] >= 3*x && num[i] + num[i-1] >= 2*x) dp[i] = 1, ans++;
}
}
cout << ans << endl;
}
return 0;
}