题意:
给定一个长度为
的数组
,问这个数组
中有多少子数组是好数组,子数组的定义为: 把一个数组前面删去
个或全部元素,后面删去
个或全部元素得到的数组就是原数组的子数组。
子数组的定义为:
- 把一个数组前面删去 个或全部元素,后面删去 个或全部元素得到的数组就是原数组的子数组
好数组的定义为:
- 对于数组a的每个子数组b都满足 则数组a就是个好数组 。
所以我们在处理某个元素 时,只看以 为右边界的子数组, 从 位置开始往左寻找,直到将和为 的子数组包含进来后停止。这时包含这个数组是不能选择的,对于每一个右端点数组元素他的子数组个数是 ,我们找到他和为 最近左端点的位置然后减去这个长度即可。
AC代码:
const int N = 2e5 + 10;
int n, m;
int a[N];
map<ll, ll> vis;
ll ans, sum, now;
int main()
{
sd(n);
rep(i, 1, n)
sd(a[i]);
vis[0] = 0;
ans = 0;
sum = 0;
now = 0;
rep(i, 1, n)
{
sum += a[i];
if (vis.count(sum) == 1) //前缀和为0的时候
now = max(now, vis[sum] + 1); //找到上一个前缀和为0的位置
vis[sum] = i;
ans += i - now;
}
pld(ans);
return 0;
}