【BZOJ3721】PA2014 Final Bazarek
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
题解:考虑如果只有一次询问该怎么做。显然我们贪心的取最大的k个物品,若总价是奇数则直接出解,若为偶数,则要么将k个物品中最小的奇数换成剩下的物品中最大的偶数,要么将k个物品中最小的偶数换成剩下物品中最大的奇数。既然是多组询问,直接维护个前缀(后缀)奇数(偶数)最大(最小)值就行了。
一开始zz了,离线用multiset求的最大最小值,结果被卡了~
#include <cstdio> #include <cstring> #include <iostream> #include <algorithm> using namespace std; typedef long long ll; int n,m; ll sum,ans[1000010],sm[2][1000010],sn[2][1000010]; int v[1000010]; int rd() { int ret=0; char gc=getchar(); while(gc<'0'||gc>'9') gc=getchar(); while(gc>='0'&&gc<='9') ret=ret*10+gc-'0',gc=getchar(); return ret; } bool cmp(int a,int b) { return a>b; } int main() { n=rd(); int i,k; for(i=1;i<=n;i++) v[i]=rd(); sort(v+1,v+n+1,cmp); sm[0][n+1]=sm[1][n+1]=-1ll<<60,sn[0][0]=sn[1][0]=1ll<<60; for(i=1;i<=n;i++) sn[v[i]&1][i]=v[i],sn[(v[i]&1)^1][i]=sn[(v[i]&1)^1][i-1]; for(i=n;i>=1;i--) sm[v[i]&1][i]=v[i],sm[(v[i]&1)^1][i]=sm[(v[i]&1)^1][i+1]; for(i=1;i<=n;i++) { sum+=v[i]; if(sum&1) ans[i]=sum; else { ans[i]=-1; ans[i]=max(ans[i],sum-sn[0][i]+sm[1][i+1]); ans[i]=max(ans[i],sum-sn[1][i]+sm[0][i+1]); } } m=rd(); for(i=1;i<=m;i++) k=rd(),printf("%lld ",ans[k]); return 0; }