CodeForeces-Summation Game

题目

题意简述

给定一个序列 \(a_1, a_2,\ldots, a_n\)

A 先选择至多 \(k\) 个数删除,B 在剩下的数中选择至多 \(x\) 个数乘上 \(-1\),双方都做出最优选择,问最终序列和最大是多少。


题目思路

对于 B 来说肯定是尽量让最大的那几个数乘上 \(-1\),对于 A 来说,并不是说删的越多越好。

3 3 1
100 100 100 

比如这个,肯定是不删的,删了反而更小了。

然后那我们该怎么办?

我们应该枚举每一次删除时的总和与前面的状态进行比较

  1. 使用 \(\max\) 函数。

  2. 然后应该排一个序从大到小,为什么排序?因为对于 B 来说它是优先选那些大的数进行变化,所以我们要排序,满足题目最优选择这个条件。

  3. 对于答案的计算,我们采用前缀和知识进行枚举即可得出最终答案。

代码实现

代码简洁并且配有注释。

#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;
}
posted @ 2025-04-16 20:00  LteShuai  阅读(9)  评论(0)    收藏  举报