BZOJ 3721: PA2014 Final Bazarek

时间:2024-01-17 09:28:32

3721: PA2014 Final Bazarek

Time Limit: 20 Sec  Memory Limit: 128 MB
Submit: 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

Sample Output

7
9
-1

HINT

Source

[Submit][Status][Discuss]

先对所有数字按照从大到小的顺序排序,然后维护前缀和,以及最小前缀(奇数/偶数),最大后缀(奇数/偶数)。

当询问K个的时候,如果sum[k]凑巧是个奇数,那么答案就是sum[k],否则就考虑用一个未添加的奇数换一个已添加的偶数,或是用一个未添加的偶数换一个已添加的奇数,二者取其大。

 #include <bits/stdc++.h>

 template <class T>
inline void read(T &x) {
char c = getchar(); x = ;
while (c < '')
c = getchar();
while (c >= '') {
x = x* + c - '';
c = getchar();
}
} template <class T>
inline T Max(const T &a, const T &b) {
return a > b ? a : b;
} template <class T>
inline T Min(const T &a, const T &b) {
return a < b ? a : b;
} inline int cmp(const void *a, const void *b) {
return - *(int *)a + *(int *)b;
} typedef long long longint; const int inf = 2e9 + ; const int siz = ; int n, m;
int num[siz];
int min[siz][];
int max[siz][];
longint sum[siz]; inline void prework(void) {
qsort(num + , n, sizeof(int), cmp); memset(sum, , sizeof(sum)); for (int i = ; i < siz; ++i)
min[i][] = min[i][] = inf,
max[i][] = max[i][] = -inf; for (int i = ; i <= n; ++i)
sum[i] = sum[i - ] + num[i]; for (int i = ; i <= n; ++i) {
int a = num[i] & , b = a ^ ;
min[i][a] = num[i];
min[i][b] = min[i - ][b];
} for (int i = n; i >= ; --i) {
int a = num[i] & , b = a ^ ;
max[i][a] = num[i];
max[i][b] = max[i + ][b];
}
} inline bool judge(int k) {
return
(min[k][] == inf || max[k + ][] == -inf)
&& (min[k][] == inf || max[k + ][] == -inf);
} inline void query(int k) {
if (sum[k] & )
printf("%lld\n", sum[k]);
else if (judge(k))puts("-1");
else printf("%lld\n",
sum[k] + Max(
- min[k][] + max[k + ][],
- min[k][] + max[k + ][])
);
} signed main(void) {
read(n); for (int i = ; i <= n; ++i)
read(num[i]); prework(); read(m); for (int i = , k; i <= m; ++i)
read(k), query(k);
}

@Author: YouSiki