这题的尺取比较秒,确定右端点,然后去数有多少个左端点满足。
当前缀和重复出现时,那就表明序列中某一段为0了,那么这是移动左端点,弄走为0区间,再继续统计。
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<iostream>
#include<vector>
#include<cmath>
#include<map>
#include<string>
#include<queue>
#include<stack>
#include<bitset>
#include<list>
#include<set>
#include<utility>
#include<functional>
#include<iomanip>
#define IO ios::sync_with_stdio(false)
#define eps 1e-7
#define int long long
using namespace std;
int t,n,a[100005*2],sum[100005*2],ans;
map<int,int>mp;
signed main()
{
IO;
cin>>n;
for(int i=1;i<=n;i++)
{
cin>>a[i];
sum[i]=sum[i-1]+a[i];
}
mp[0]++;
int l=0,r=1;
while(r<=n)
{
while(mp[sum[r]])
{
//cout<<"123:"<<l<<" "<<sum[l]<<endl;
mp[sum[l++]]=0;//例如 1 2 1 2 -3 2,直至把0那一段分开了为止
}
ans+=r-l;//a[l+1]~a[r] to a[r]~a[r]依次添加
//cout<<l<<" "<<r<<endl;
mp[sum[r]]=1;
r++;
}
cout<<ans;
}