传送门:https://codeforces.com/contest/1333/problem/C
题意:如果一个数组的子数组(连续)里的值相加都不为0,那么称他为好数组,给出一个数组,问他的多少子数组是好数组(包括它本身)
一个好数组就不含总价值为0的子数组,那么如何判断他含不含总价值为0的子数组呢?
一个前缀和就搞得定,两个前缀和相等的数中间夹着的就是总价值为0的子数组,对吧
那么问题就变成了:对于每个以R为右端点的子数组,如何找到最小的左端点L,满足前缀和区间[L,R]的数字都不相同
然后双指针维护
#include<bits/stdc++.h> using namespace std; #define ll long long int a[200009],b[200009],z[200009]; ll sum[200009]; int main() { int n; scanf("%d",&n); for(int i=1;i<=n;i++) scanf("%d",&a[i]),sum[i]=sum[i-1]+a[i]; map<ll,int>mp; ll ans=0; int l=0; mp[0]=1; for(int i=1;i<=n;i++) { while(mp[sum[i]]) mp[sum[l++]]--; mp[sum[i]]++; ans+=(i-l); } printf("%lld ",ans); return 0; }