【BZOJ3721】PA2014 Final Bazarek 贪心

【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

Sample Output

7
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\n",ans[k]);
	return 0;
}

 

posted @ 2017-07-25 20:56  CQzhangyu  阅读(303)  评论(0编辑  收藏  举报