题目大意
一个人要统计他所在公司的总收入并且他想使总收入达到最大,收入写在一条清单上,总收入是清单上所有数之和。
他有 \(k\) 次操作的机会,每次操作可以将某个数一个数变成其相反数,例如 \(1\) 变成 \(-1\) (注意,他必须严格执行 \(k\) 次)问总收入最大是多少?
题目分析
将数组从小到大排序后:
在前 \(m\) 个数中,我们取出负数并取反,若 \(\ge0\) 则马上退出。将这些数取反之后,就能够将 \(\sum\limits_{i=1}^{n}a_i\) 的和变得更大。
若 \(m\) 将这些负数取反后还有剩余,那么再分类讨论:
-
若 \(m\) 为偶数,则偶数次操作后 \(a\) 的值不变。
-
若 \(m\) 为奇数,则只需操作一次就等价于操作 \(m\) 次操作,将最小值取反即可。
代码
细节巨多。。。
#include<iostream>
#include<algorithm>
using namespace std;
typedef long long ll;
const int MAXN = 1e5 + 20;
int n, k;
int vec[MAXN];
int main() {
ios::sync_with_stdio(false);
cin.tie(0),cout.tie(0);
cin >> n >> k;
for (int i = 0; i < n; i++) cin >> vec[i];
sort(vec, vec + n);
int b = 0;
while (b < n && k--) {
if (vec[b] >= 0) {
k++;
break;
}
vec[b++] *= -1;
}
if (k < 0) k = 0;
sort(vec, vec + n);
if (vec[0] == 0 || k % 2 == 0) {
ll sum = 0;
for (int i = 0; i < n; i++) sum += vec[i];
cout << sum << endl;
return 0;
}
vec[0] *= -1;
ll sum = 0;
for (int i = 0; i < n; i++) sum += vec[i];
cout << sum << endl;
return 0;
}