CF 1616D. Keep the Average High

传送门

 

 1 /*
 2 思路:把 a1 + a2 + ... + an >= x * (r - l + 1)  
 3         ===>  a1 + a2 + ... + an - x * (r - l + 1) >= 0
 4     可以等价为对于每个(ai - x) 得到新的ai,则题目变为对于任意区间[l, r], al + ... + ar >= 0.
 5     
 6     我们先考虑: ai分布为  + - + - + - ...  (ai正负交替出现)
 7      
 8     对于 ( a1(-) a2(+) a3(-) ) 这相邻的三个数, 
 9     如果a1 + a2 < 0 和 a2 + a3 < 0只满足其一,则容易想到把满足等式的那个ai(-)不取.
10     如果两个都满足,则需要用到贪心的思想,我们应该不取中间的a2,因为a2不取,
11     使得我们可能可以取a1, a3; 如果是不取a1, a3则只有a2可以取.
12     
13     如果上述两个等式都不成立,而 a1 + a2 + a3 < 0,则我们贪心的让a3(-)不取,这样对于后面的取与不取有意义
14     
15     当然,对于ai(-)如果已经确定是不取的情况得判定
16     
17     其他的就是一般的情况   - + - + + + - + + - - -
18     我们就可以知道,只需要对于ai(+)来判断左右的情况即可.
19     对于ai(-)则只需判断前面一个元素是不是负数,是不是不取来判断自己是不是不取,因为两个(-)一定是不满足题意的.
20     
21     从最小的相邻的局部满足可以得到整体的满足.
22 */
23 
24 
25 
26 
27 #include <bits/stdc++.h>
28 using namespace std;
29 
30 #define ll long long
31 #define ANS cout<<"ans: ";
32 
33 const int N = 1e6 + 10;
34 
35 int a[N];
36 struct node {
37     int v;
38     int w;//改数取不取
39 };
40 int n;
41 
42 inline bool check (int x, int id)
43 {
44     if(id == 0) return x - 1 >= 0;
45     else return x + 1 < n;
46 }
47 
48 void solve ()
49 {
50     int T;
51     cin >> T;
52     while(T --) {
53 
54         cin >> n;
55         for(int i = 1; i <= n; i ++) cin >> a[i];
56 
57         int x;
58         cin >> x;
59 
60         vector<node > vn;
61         for(int i = 1; i <= n; i ++) vn.push_back({a[i] - x, 1});
62 
63         int tot = 0;
64         for(int i = 0; i < n; i ++) {
65             if(vn[i].v >= 0) {
66                 int l, r;
67                 l = r = 0;
68                 if(check(i, 0) && vn[i - 1].v < 0 && vn[i - 1].w == 1 && vn[i].v + vn[i - 1].v < 0) l = 1;
69                 if(check(i, 1) && vn[i + 1].v < 0 && vn[i + 1].w == 1 && vn[i].v + vn[i + 1].v < 0) r = 1;
70                 if(l + r == 2) tot ++;
71                 else if(l == 1) tot ++, vn[i - 1].w = 0;
72                 else if(r == 1) tot ++, vn[i + 1].w = 0;
73                 else if(l + r == 0) {
74                     int sum = vn[i].v;
75                     if(check(i, 0) && vn[i - 1].v < 0 && vn[i - 1].w == 1) sum += vn[i - 1].v;
76                     if(check(i, 1) && vn[i + 1].v < 0 && vn[i + 1].w == 1) sum += vn[i + 1].v;
77                     if(sum < 0) tot ++, vn[i + 1].w = 0;
78                 }
79             } else if(vn[i].v < 0 && vn[i].w == 1) {
80                 if(check(i, 0) && vn[i - 1].v < 0 && vn[i - 1].w == 1) tot ++, vn[i].w = 0;
81             }
82         }
83 
84         ANS;
85         cout << n - tot << endl;
86     }
87 }
88 
89 int main()
90 {
91     solve();
92 
93     return 0;
94 }

 

posted @ 2022-01-06 16:37  SummerMingQAQ  阅读(118)  评论(0编辑  收藏  举报