CodeForeces-Summation Game
题目

题意简述
给定一个序列 \(a_1, a_2,\ldots, a_n\)。
A 先选择至多 \(k\) 个数删除,B 在剩下的数中选择至多 \(x\) 个数乘上 \(-1\),双方都做出最优选择,问最终序列和最大是多少。
题目思路
对于 B 来说肯定是尽量让最大的那几个数乘上 \(-1\),对于 A 来说,并不是说删的越多越好。
3 3 1
100 100 100
比如这个,肯定是不删的,删了反而更小了。
然后那我们该怎么办?
我们应该枚举每一次删除时的总和与前面的状态进行比较。
-
使用 \(\max\) 函数。
-
然后应该排一个序从大到小,为什么排序?因为对于 B 来说它是优先选那些大的数进行变化,所以我们要排序,满足题目最优选择这个条件。
-
对于答案的计算,我们采用前缀和知识进行枚举即可得出最终答案。
代码实现
代码简洁并且配有注释。
#include <iostream>
#include <algorithm>
using namespace std;
bool cmp(int a, int b) {
return a > b;
}
int a[200010];
int s[200010];
void solve() {
int n, k, x;
cin >> n >> k >> x;
int sum = 0;
for (int i = 1; i <= n; i ++ ) {
cin >> a[i];
sum += a[i];
}
sort(a + 1, a + 1 + n, cmp);
for (int i = 1; i <= n; i ++ ) {
s[i] = s[i - 1] + a[i];
}
for (int i = n + 1; i <= n + max(k, x) + 10; i++) {
s[i] = s[n];
}//防止多测 之前的数据出现意外,所以给n后面的也保存下
int g = x;
int ans = -1e9;
int f = 0;//循环的条件 表示删除的次数
while (f <= k) {
ans = max(ans, sum - s[g] - (s[g] - s[f]));
//sum-sg表示此时序列的和 sg-sf表示所选的数(*-1)的值
f++;
g++;
}
cout << ans << endl;
return ;
}
int main() {
int t ;
cin >> t;
while (t--)solve();
return 0;
}

浙公网安备 33010602011771号