分类讨论加贪心解题。
( 1 1 1)读入数据,将其存放到数组 A A A 中,复制数组 A A A 的所有元素到数组 B B B 中。
( 2 2 2)将数组 A A A 的元素按绝对值大小递减排序,数组 B B B 的元素按大小递增排序。
( 3 3 3)将数组 A A A 中前 K K K 个数按正数、负数、零进行分类,令正数的个数为 P P P,负数的个数为 D D D,零的个数为 Z Z Z,然后分类讨论。
( 4 4 4)若 Z > 0 Z > 0 Z>0,即有零元素,显然最大乘积为零,统计数组 B B B 中后 K K K 个元素之和即可。
( 5 5 5)若 Z = = 0 Z == 0 Z==0 且 D = = 0 D == 0 D==0,即绝对值较大的 K K K 个数全为正数,统计数组 B B B 中后 K K K 个元素之和即可。
( 6 6 6)若 Z = = 0 Z == 0 Z==0 且 P = = 0 P == 0 P==0,由于奇数个负数的积仍为负数,需要根据 K K K 的奇偶性进行选择。
( 6.1 6.1 6.1)若 K K K 为偶数,则前 K K K 个负数的积为正数,此时统计数组 B B B 的前 K K K 个元素之和即可。
( 6.2 6.2 6.2)若 K K K 为奇数,分两种情况:
( 6.2.1 6.2.1 6.2.1) 如果数组 A A A 中除了前 K K K 个元素外没有正数,那么最大积要么为零,要么为负数,则取数组 B B B 的后 K K K 个元素相乘能够得到最大的积且同时和最大;
( 6.2.2 6.2.2 6.2.2)如果数组 A A A 中除了前 K K K 个元素外还有正数,则取绝对值最大的正数替换掉第 K K K 个负数,则可保证积为正,此时取数组 A A A 中的前 K − 1 K - 1 K−1 个负数加上数组 B B B 的最后一个元素相乘能够得到最大的积且同时和最大;
( 7 7 7)若 Z = = 0 Z == 0 Z==0 且 P > 0 P > 0 P>0 且 D > 0 D > 0 D>0,根据 D D D 的奇偶性进行选择。
( 7.1 7.1 7.1)若 D D D 为偶数,则偶数个负数的积为正数,将数组 A A A 中前 K K K 个元素相乘能够得到最大的积且同时和最大;
( 7.2 7.2 7.2)若 D D D 为奇数,则考虑将一个正数替换为负数,或将一个负数替换为正数,这样能够保证负数的数量为偶数,从而能够得到正的积。此时从数组 A A A 中的第 K + 1 K + 1 K+1 个元素开始,寻找绝对值最大的一个正数和绝对值最大的一个负数,令其分别为 P B PB PB 和 N B NB NB,此时有以下几种情形:
( 7.2.1 7.2.1 7.2.1) P B PB PB 和 N B NB NB 均不存在,表明数组 A A A 中除了前 K K K 个元素外要么全为 0 0 0,要么 K = = N K == N K==N,此时,将数组 B B B 中后 K K K 个元素相乘能够得到最大的积且同时和最大。
( 7.2.2 7.2.2 7.2.2) P B PB PB 存在, N B NB NB 不存在,将 P B PB PB 替换数组 A A A 中前 K K K 个元素中绝对值最小的那个负数即可。
( 7.2.3 7.2.3 7.2.3) P B PB PB 不存在, N B NB NB 存在,将 N B NB NB 替换数组 A A A 中前 K K K 个元素中绝对值最小的那个正数即可。
( 7.2.4 7.2.4 7.2.4) P B PB PB 和 N B NB NB 均存在,令数组 A A A 中前 K K K 个元素中绝对值最小的正数为 P S PS PS,绝对值最小的负数为 N S NS NS,若 P B × P S > = N B × N S PB \times PS >= NB \times NS PB×PS>=NB×NS,则将 P B PB PB 替换 N S NS NS,否则将 N B NB NB 替换 P S PS PS。
// Maximum Subsequence
// UVa ID: 10747
// Verdict: Accepted
// Submission Date: 2021-11-12
// UVa Run Time: 0.020s
//
// 版权所有(C)2021,邱秋。metaphysis # yeah dot net
#include <bits/stdc++.h>
using namespace std;
int ai[10010], bi[10010], positive[10010], negative[10010], pc, nc, zero, N, K;
void sumFirstK()
{
cout << accumulate(bi, bi + K, 0) << '\n';
}
void sumLastK()
{
cout << accumulate(bi + N - K, bi + N, 0) << '\n';
}
int sumAll()
{
int sum = accumulate(positive, positive + pc, 0);
sum += accumulate(negative, negative + nc, 0);
return sum;
}
bool cmp(int a, int b)
{
if (abs(a) != abs(b)) return abs(a) > abs(b);
return a > b;
}
int main(int argc, char *argv[])
{
cin.tie(0), cout.tie(0), ios::sync_with_stdio(false);
while (cin >> N >> K)
{
if (N == 0) break;
for (int i = 0; i < N; i++) { cin >> ai[i]; bi[i] = ai[i]; }
sort(ai, ai + N, cmp);
sort(bi, bi + N);
pc = nc = zero = 0;
for (int i = 0; i < K; i++)
{
if (ai[i] == 0) { zero = 1; break; }
if (ai[i] > 0) positive[pc++] = ai[i];
else negative[nc++] = ai[i];
}
if (zero || !nc) { sumLastK(); continue; }
if (!pc)
{
if (K % 2 == 0) sumFirstK();
else
{
if (bi[N - 1] <= 0) sumLastK();
else
{
int sum = accumulate(ai, ai + K - 1, 0) + bi[N - 1];
cout << sum << '\n';
}
}
}
else
{
if (nc % 2 == 0) cout << sumAll() << '\n';
else
{
int pb, nb, pflag = 0, nflag = 0;
for (int i = K; i < N && (!pflag || !nflag); i++)
{
if (ai[i] > 0 && !pflag)
{
pflag = 1;
pb = ai[i];
}
if (ai[i] < 0 && !nflag)
{
nflag = 1;
nb = ai[i];
}
}
if (pflag && nflag)
{
if (positive[pc - 1] * pb >= negative[nc - 1] * nb)
{
int sum = sumAll() - negative[nc - 1] + pb;
cout << sum << '\n';
}
else
{
int sum = sumAll() - positive[pc - 1] + nb;
cout << sum << '\n';
}
}
else if (pflag)
{
int sum = sumAll() - negative[nc - 1] + pb;
cout << sum << '\n';
}
else if (nflag)
{
int sum = sumAll() - positive[pc - 1] + nb;
cout << sum << '\n';
}
else sumLastK();
}
}
}
return 0;
}