1. 程式人生 > >BZOJ 3721: PA2014 Final Bazarek

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 }
View Code