题意:给你
n
个正整数,m次询问,每次给定一个
k
,要求选择k个数和为奇数且最大,输出这个最大和。无解输出-1.
题解:贪心,先对所有数去排序,如果最大的
k
<script type="math/tex" id="MathJax-Element-141">k</script>个数的和为奇数,显然就是答案。如果最大的k个数之和是偶数,那么我可以将后k个数中最小的偶数换成前n-k个数中最大的奇数,或者将后k个数中最小的奇数换成前n-k个数中最大的偶数。
#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;
}