首页 > 代码库 > BZOJ 3727 PA2014 Final Zadanie 贪心

BZOJ 3727 PA2014 Final Zadanie 贪心

题目大意:给定n个数,多次询问选择k个数使和为奇数的最大和

首先将所有数排序

对于每个询问,如果最大的k个数之和是奇数,那么答案显然是这k个数的和

如果最大的k个数之和是偶数,那么我可以将后k个数中最小的偶数换成前n-k个数中最大的奇数,或者将后k个数中最小的奇数换成前n-k个数中最大的偶数

二者取最优即可 无法如此做则输出-1

#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#define M 1001001
using namespace std;
int n,m,k,a[M];
long long min_num[M][2],pre[M][2];
long long sum[M],ans;
int main()
{
    int i;
    cin>>n;
    for(i=1;i<=n;i++)
        scanf("%d",&a[i]);
    sort(a+1,a+n+1);
    min_num[n+1][0]=min_num[n+1][1]=1e15;
    for(i=n;i;i--)
    {
        sum[i]=sum[i+1]+a[i];
        min_num[i][a[i]&1]=a[i];
        min_num[i][~a[i]&1]=min_num[i+1][~a[i]&1];
    }
    pre[0][0]=pre[0][1]=-1e15;
    for(i=1;i<=n;i++)
    {
        pre[i][a[i]&1]=a[i];
        pre[i][~a[i]&1]=pre[i-1][~a[i]&1];
    }
     
    cin>>m;
    for(i=1;i<=m;i++)
    {
        scanf("%d",&k);
        if(sum[n-k+1]&1)
        {
            printf("%lld\n",sum[n-k+1]);
            continue;
        }
        ans=sum[n-k+1];
        long long x=min_num[n-k+1][0]-pre[n-k][1];
        long long y=min_num[n-k+1][1]-pre[n-k][0];
        if(x>=1e14&&y>=1e14)
        {
            puts("-1");
            continue;
        }
        ans-=min(x,y);
        printf("%lld\n",ans);
    }
}


BZOJ 3727 PA2014 Final Zadanie 贪心