3721: PA2014 Final Bazarek
Time Limit: 20 Sec Memory Limit: 128 MBSubmit: 645 Solved: 261
[Submit][Status][Discuss]
Description
有n件商品,选出其中的k个,要求它们的总价为奇数,求最大可能的总价。
Input
第一行一个整数n(1<=n<=1000000),表示商品数量。
接下来一行有n个整数,表示每件商品的价格,范围在[1,10^9]。
接下来一行有一个整数m(1<=m<=1000000),表示询问数量。
接下来m行,每行一个整数k[i](1<=k[i]<=n)。
Output
对于每个询问,输出一行表示保证奇数的情况下最大的总价。若无法满足要求,输出-1。
Sample Input
4
4 2 1 3
3
2
3
4
4 2 1 3
3
2
3
4
Sample Output
7
9
-1
9
-1
HINT
Source
先对所有数字按照从大到小的顺序排序,然后维护前缀和,以及最小前缀(奇数/偶数),最大后缀(奇数/偶数)。
当询问K个的时候,如果sum[k]凑巧是个奇数,那么答案就是sum[k],否则就考虑用一个未添加的奇数换一个已添加的偶数,或是用一个未添加的偶数换一个已添加的奇数,二者取其大。
1 #include <bits/stdc++.h> 2 3 template <class T> 4 inline void read(T &x) { 5 char c = getchar(); x = 0; 6 while (c < '0') 7 c = getchar(); 8 while (c >= '0') { 9 x = x*10 + c - '0'; 10 c = getchar(); 11 } 12 } 13 14 template <class T> 15 inline T Max(const T &a, const T &b) { 16 return a > b ? a : b; 17 } 18 19 template <class T> 20 inline T Min(const T &a, const T &b) { 21 return a < b ? a : b; 22 } 23 24 inline int cmp(const void *a, const void *b) { 25 return - *(int *)a + *(int *)b; 26 } 27 28 typedef long long longint; 29 30 const int inf = 2e9 + 9; 31 32 const int siz = 1000005; 33 34 int n, m; 35 int num[siz]; 36 int min[siz][2]; 37 int max[siz][2]; 38 longint sum[siz]; 39 40 inline void prework(void) { 41 qsort(num + 1, n, sizeof(int), cmp); 42 43 memset(sum, 0, sizeof(sum)); 44 45 for (int i = 0; i < siz; ++i) 46 min[i][0] = min[i][1] = inf, 47 max[i][0] = max[i][1] = -inf; 48 49 for (int i = 1; i <= n; ++i) 50 sum[i] = sum[i - 1] + num[i]; 51 52 for (int i = 1; i <= n; ++i) { 53 int a = num[i] & 1, b = a ^ 1; 54 min[i][a] = num[i]; 55 min[i][b] = min[i - 1][b]; 56 } 57 58 for (int i = n; i >= 1; --i) { 59 int a = num[i] & 1, b = a ^ 1; 60 max[i][a] = num[i]; 61 max[i][b] = max[i + 1][b]; 62 } 63 } 64 65 inline bool judge(int k) { 66 return 67 (min[k][0] == inf || max[k + 1][1] == -inf) 68 && (min[k][1] == inf || max[k + 1][0] == -inf); 69 } 70 71 inline void query(int k) { 72 if (sum[k] & 1) 73 printf("%lld\n", sum[k]); 74 else if (judge(k))puts("-1"); 75 else printf("%lld\n", 76 sum[k] + Max( 77 - min[k][0] + max[k + 1][1], 78 - min[k][1] + max[k + 1][0]) 79 ); 80 } 81 82 signed main(void) { 83 read(n); 84 85 for (int i = 1; i <= n; ++i) 86 read(num[i]); 87 88 prework(); 89 90 read(m); 91 92 for (int i = 1, k; i <= m; ++i) 93 read(k), query(k); 94 }
@Author: YouSiki