【PA2014Final】【BZOJ3721】Bazarek

本文介绍了一种算法解决方案,用于从给定的商品集合中选择特定数量的商品,使得这些商品的总价为奇数,并最大化该总价。文章详细解释了通过排序、记录前缀和以及区分奇偶数来高效解决这个问题的方法。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

Description

有n件商品,选出其中的k个,要求它们的总价为奇数,求最大可能的总价。
Input

第一行一个整数n(1<=n<=1000000),表示商品数量。
接下来一行有n个整数,表示每件商品的价格,范围在[1,10^9]。
接下来一行有一个整数m(1<=m<=1000000),表示询问数量。
接下来m行,每行一个整数ki
Output

对于每个询问,输出一行表示保证奇数的情况下最大的总价。若无法满足要求,输出-1。
Sample Input
4
4 2 1 3
3
2
3
4
Sample Output
7
9
-1
HINT

Source

鸣谢Jcvb

省队集训时候Delayyy讲过的题.
贪心.
把所有数从大到小排序记录前缀和,然后分奇偶性,然后对奇数偶数分别记录前缀最小后缀最大来回答询问.
前k个前缀和为奇,则直接输出就行了
否则考虑以奇换偶或者以偶换奇.

#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
#define MAXINT 0x7fffffff
#define MAXN 1000100
#define LL long long
using namespace std;
int n,m,q;
int k[MAXN];
LL pre[MAXN],min1[MAXN],min2[MAXN],max1[MAXN],max2[MAXN],ans;
void in(int &x)
{
    char ch=getchar();x=0;int flag=1;
    while (!(ch>='0'&&ch<='9')) flag=ch=='-'?-1:flag,ch=getchar();
    while (ch>='0'&&ch<='9')    x=x*10+ch-'0',ch=getchar();x*=flag;
}
bool cmp(LL a,LL b)
{
    return a>b;
}
int main()
{
    in(n);
    for (int i=1;i<=n;i++)  in(k[i]);
    sort(k+1,k+n+1,cmp);
    for (int i=1;i<=n;i++)  pre[i]=pre[i-1]+k[i];
    min1[0]=MAXINT;min2[0]=MAXINT;
    for (int i=1;i<=n;i++)
    {
        min1[i]=min1[i-1];min2[i]=min2[i-1];
        if (k[i]&1) min1[i]=min(min1[i],(LL)k[i]);
        else    min2[i]=min(min2[i],(LL)k[i]);
    }
    for (int i=n;i;i--)
    {
        max1[i]=max1[i+1];max2[i]=max2[i+1];
        if (k[i]&1) max1[i]=max(max1[i],(LL)k[i]);
        else    max2[i]=max(max2[i],(LL)k[i]);
    }
    in(m);
    for (int i=1;i<=m;i++)
    {
        in(q);
        if (pre[q]&1)   printf("%lld\n",pre[q]);
        else
        {
            ans=-1;
            if (min1[q]!=MAXINT&&max2[q+1]) ans=max(ans,pre[q]-min1[q]+max2[q+1]);
            if (min2[q]!=MAXINT&&max1[q+1]) ans=max(ans,pre[q]-min2[q]+max1[q+1]);
            printf("%lld\n",ans);
        }
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值