12/27 cf Goodbye2025 C solution

28 阅读2分钟

题目

Problem - C - Codeforces

思路

因为最后只剩一个小朋友没入选,所以我们自然想到要找到那个落单的小朋友。

先简单举一个例子:如果有5个小朋友,niceness为ai.

  1. 如果不选一号小朋友,剩下4个的贡献都是-ai;
  2. 如果不选二号小朋友,其余4个的贡献为:+a1,-a3,-a4,-a5;
  3. 如果不选三号小朋友,其余4个的贡献为:+a1,+a2/-a2,-a4,-a5;
  4. 如果不选四号小朋友,其余4个的贡献为:+a1,+a2/-a2,+a3/-a3,-a5;
  5. 如果不选五号小朋友,其余4个的贡献为:+a1,+a2/-a2,+a3/-a3,+a4/-a4;

不难发现,第一个小朋友的贡献始终为+a1,不选的小朋友之前的小朋友(除一号小朋友)的贡献+-都可取到,所以要求最大值,我们就取|ai|。不选的小朋友之后的小朋友的贡献只能说-ai。

所以我们可以预处理|ai|的前缀和(不含a1)和-ai的后缀和。

时间复杂度:O(n)

AC code

#include <bits/stdc++.h>
using namespace std;
#define int long long
#define endl '\n'
void solve() {
	int n;
	cin >> n;
	vector<int>a(n);
	for (int i = 0;i < n;++i)cin >> a[i];
	vector<int>pf(n + 1), sf(n + 1);
	for (int i = 1;i < n;++i)pf[i + 1] = pf[i] + abs(a[i]);//前缀和(不含a1的|ai|),注意下标的计算
	for (int i = n - 1;i >= 1;i--)sf[i - 1] = sf[i] - a[i];//-ai的后缀和,注意下标的计算
	int ans = sf[0];
	for (int i = 1;i < n;++i)ans = max(ans, a[0] + pf[i] + sf[i]);
	cout << ans << endl;
}
signed main() {
	ios::sync_with_stdio(false), cin.tie(0), cout.tie(0);
	int t = 1;
	cin >> t;
	while (t--) {
		solve();
	}
	return 0;
}

我赛时没想到的点:

  1. |ai|
  2. 下标计算给自己绕晕了