BZOJ 3721 PA2014 Final Bazarek

題意:給你n 個正整數,m 次詢問,每次給定一個k ,要求選擇k 個數和爲奇數且最大,輸出這個最大和。無解輸出-1.

題解:貪心,先對所有數去排序,如果最大的k 個數的和爲奇數,顯然就是答案。如果最大的k個數之和是偶數,那麼我可以將後k個數中最小的偶數換成前n-k個數中最大的奇數,或者將後k個數中最小的奇數換成前n-k個數中最大的偶數。

/*
    ID:Agreement
*/
//invincible

#include <bits/stdc++.h>
#define rep( i , l , r ) for( int i = (l) ; i <= (r) ; ++i )
#define per( i , r , l ) for( int i = (r) ; i >= (l) ; --i )
#define erep( i , u ) for( int i = head[(u)] ; ~i ; i = e[i].nxt )
using namespace std;
typedef long long ll;
const int maxn = 2e6;
ll a[maxn];
ll pre_odd[maxn] , pre_even[maxn] , suf_odd[maxn] , suf_even[maxn] , sum[maxn];
bool cmp( ll a , ll b ){ return a > b; }
int main(){
    int N = 0;
    scanf("%d" , &N);
    rep( i , 1 , N ) scanf("%lld" , &a[i] );
    sort( a + 1 , a + 1 + N , cmp );
    rep( i , 1 , N ) sum[i] = sum[i - 1] + a[i];
    pre_odd[0] = pre_even[0] = -1;
    rep( i , 1 , N )
         if( a[i] & 1 ) pre_odd[i] = a[i] , pre_even[i] = pre_even[i - 1];
         else pre_odd[i] = pre_odd[i - 1] , pre_even[i] = a[i];
    suf_odd[N + 1] = suf_even[N + 1] = -1;
    per( i , N , 1 )
         if( a[i] & 1 ) suf_odd[i] = a[i] , suf_even[i] = suf_even[i + 1];
         else suf_odd[i] = suf_odd[i + 1] , suf_even[i] = a[i];
    int T = 0 , k;
    scanf("%d" , &T);
    while( T-- ){
        scanf("%d" , &k);
        if( sum[k] & 1 ) printf("%lld\n" , sum[k] );
        else{
            ll res = -1;
            if( pre_even[k] != -1 && suf_odd[k + 1] != -1 ) res = max( res , sum[k] - pre_even[k] + suf_odd[k + 1] );
            if( pre_odd[k] != -1 && suf_even[k + 1] != -1 ) res = max( res , sum[k] - pre_odd[k] + suf_even[k + 1] );
            printf("%lld\n" , res );
        }
    }
    return 0;
}

發佈了48 篇原創文章 · 獲贊 3 · 訪問量 4055
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章