Codeforces 1333C Eugene and an array

Posted syksykccc

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Codeforces 1333C Eugene and an array相关的知识,希望对你有一定的参考价值。

我们记 $f_i$ 表示 以 $i$ 结尾的合法段的个数,显然,这题就是要我们求 $sum_{i=1}^{n} f_i$。

我们考虑依次求出每一个 $f_i$。设想,我们这次要求的段的右端点显然都是 $i$,左端点可以是 $[1, i]$ 中的每一个值。那么哪些左端点是合法的呢?显然这是一个后缀,也就是说,如果左端点是 $p$ 的时候已经不合法了,那么左端点是 $q$($q<p$)的时候显然是不合法的,因为后者包含了 前者所包含的全部子段

那么我们只要求出最小的合法的位置 $p$,就知道 $f_i = i - p + 1$ 了(即 $[p, i]$ 中的位置的个数)。我们知道 $i$ 以前可能会有若干个和为 $0$ 的段,那么,$p$ 就是这些段的 左端点的最大值 $ extbf{+1}$,因为当 $p$ 小于等于这个左端点的最大值时,这个含有最大左端点的 $0$ 段就一定被完整包含了。

所以我们可以每次计算完 $i$ 的贡献后更新这个左端点的最大值。显然只要计算一遍前缀和(仍然存在 $a$ 中),那么如果有一个位置 $j$($j < i$)满足 $a_j = a_i$,那么 $[j+1,i]$ 就是一个 $0$ 段。这里我们可以用 map 来存储一下上一次出现某个数的位置,记作 $lastpos_{a_i}$,那么 $[lastpos_{a_i} + 1, i]$ 就是一个 $0$ 段,左端点为 $lastpos_{a_i} + 1$。那么第 $i$ 个数考虑过后的 $p$,就是 $max{ ext{old } p, (lastpos_{a_i}+1)+1}$。

程序里面为了方便,存储的 maxl 其实就是 $p - 1$,那么更新答案应该改为 $i - (p - 1) = i - maxl$。

#include <bits/stdc++.h>
#define int long long
using namespace std;
int n, a[200005], ans;
map<int, int> lastpos;
signed main()
{
	lastpos[0] = 0;
	cin >> n;
	for(int i = 1; i <= n; i++)
	{
		cin >> a[i];
		a[i] += a[i - 1];
	}
	for(int i = 1, maxl = 0; i <= n; i++)
	{
		if(lastpos.count(a[i])) maxl = max(maxl, lastpos[a[i]] + 1);
		ans += i - maxl;
		lastpos[a[i]] = i;
	}
	cout << ans << endl;
	return 0;
}

以上是关于Codeforces 1333C Eugene and an array的主要内容,如果未能解决你的问题,请参考以下文章

CodeForces 1333-C Eugene and an array(子区间和为0前缀和)

[每日一题]:Codeforces Round #632 (Div. 2) C. Eugene and an array

cf C. Eugene and an array

[读书笔记]平面波的数学表示 Optics 5th 作者Eugene Hecht

英语----非谓语动词联系

codeforces#341