BZOJ 3721: PA2014 Final Bazarek
排序后,如果前k个是奇数,那么直接输出
如果不是,我们考虑两种方式来变成奇数
第一种,$去掉第k个数,然后在[k + 1, n] 中找一个与第k个数奇偶性不同的数替换上去$
第二种,$选择第k + 1个数,然后在[1, k] 中选择一个与第k + 1个数奇偶性不同的数减去$
注意要特判$n == k 的情况$
考虑为什么这样可以,因为我们要想改变奇偶性,肯定要选择一个奇偶性不同的来换掉其中一个数
那么就有上面两种方式
那么会不会有可能存在换掉两个数或者更多的数使得答案更优呢 ,答案是不会
因为如果假设这样正确的话,那么必定存在奇数对数,他们的奇偶性不同,也就是说至少存在一对数,奇偶性不同
那么显然,我们只替换掉其中一对代价最小的,其他都不变,答案会更优
1 #include <bits/stdc++.h> 2 using namespace std; 3 4 #define ll long long 5 #define N 1000010 6 int n, q; 7 ll a[N], sum[N], pre[N], suf[N]; 8 9 bool cmp (int a, int b) { return a > b; } 10 int main() 11 { 12 while (scanf("%d", &n) != EOF) 13 { 14 for (int i = 1; i <= n; ++i) 15 scanf("%lld", a + i); 16 sort(a + 1, a + 1 + n, cmp); 17 for (int i = 1; i <= n; ++i) sum[i] = sum[i - 1] + a[i]; 18 ll odd = -1, even = -1; 19 for (int i = 1; i <= n; ++i) 20 { 21 if (a[i] & 1) 22 { 23 pre[i] = even; 24 odd = a[i]; 25 } 26 else 27 { 28 pre[i] = odd; 29 even = a[i]; 30 } 31 } 32 odd = even = -1; 33 for (int i = n; i >= 1; --i) 34 { 35 if (a[i] & 1) 36 { 37 suf[i] = even; 38 odd = a[i]; 39 } 40 else 41 { 42 suf[i] = odd; 43 even = a[i]; 44 } 45 } 46 scanf("%d", &q); 47 for (int qq = 1, k; qq <= q; ++qq) 48 { 49 scanf("%d", &k); 50 if (sum[k] & 1) printf("%lld\n", sum[k]); 51 else if (k == n) puts("-1"); 52 else 53 { 54 ll tmp = -1; 55 if (suf[k] != -1) tmp = sum[k - 1] + suf[k]; 56 if (pre[k + 1] != -1) tmp = max(tmp, a[k + 1] + sum[k] - pre[k + 1]); 57 printf("%lld\n", tmp); 58 } 59 } 60 } 61 return 0; 62 }