CF1748C Zero-Sum Prefixes

题链:cf luogu

有意思的统计题。

Description

给你一个长度为 \(n\) 的整数序列 \(A\),你可以将其中的 \(0\) 替换为任意的 \(x(x\in\mathbb{Z})\)

问经替换后最多有多少个 \(i\) 满足 \(\sum^{i}_{j=1}a_j=0\)

Analysis

考虑每一个 \(0\) 可以控制到下一个 \(0\) 之间的前缀和 \(=0\) 数。这点容易想到,于是发现分段处理。

对每两个 \(0\) 之间的位置求前缀和众数(可以使用 Hashstd:: map),设众数为 \(x\),则前面的 \(0\) 可以替换为 \(-x\) 以得最优解。

注意:第一个 \(0\) 前的原始为 \(0\) 的前缀和不要漏统。

Code

#include <stdio.h>
#include <map>
#define int long long
const int N = (int)2e5 + 5;
int n, a[N], s[N];
inline void Solve() {
	scanf("%lld", &n); s[0] = 0;
	for (int i = 1; i <= n; ++i) {
		scanf("%lld", &a[i]);
		s[i] = s[i - 1] + a[i];
	}
	int ans = 0, st;
	for (st = 1; st <= n && a[st]; ++st)
		if (!s[st]) ++ans;
	for (int i = st, j; i <= n; i = j) {
		std:: map<int, int> cnt; int now = 1;
		for (j = i + 1; j <= n && a[j]; ++j);
		for (int k = i; k < j; ++k) {
			++cnt[s[k]];
			if (cnt[s[k]] > now) now = cnt[s[k]];
		}
		ans += now;
	}
	printf("%lld\n", ans);
}
signed main(void) {
	int T; for (scanf("%lld", &T); T--; ) Solve();
	return 0;
}

Postscript

至今不知道为什么写成 unordered_map 会超时,

但写成 map 肯定能过。

不说再见

posted @ 2022-11-15 17:15  Dry_ice  阅读(144)  评论(0)    收藏  举报