CF1333C Eugene and an array(双指针算法)
根据题目的性质,他要求的子串没有和为0的情况,所谓子串,就是枚举任意一个左端点和右端点的串。我们知道子串的个数是(n+1)*n/2-1(是否为空)
显然超复杂度了,但是我们可以进一步想到,如果只枚举右端点,左端点根据题目的要求变化判断,这种双指针的复杂度,显然只有O(N)
我们又想到,一段区间的和,都可以用前缀和来维护,并且如果l-r为0,说明s[r]=s[l-1],所以我们用一个map来维护前缀和,判断移动
这样复杂度就是O(NlogN)
#include<iostream> #include<algorithm> #include<cstring> #include<cstdio> #include<map> #include<string> #include<vector> using namespace std; typedef long long ll; const int N=2e5+5; int a[N]; ll s[N]; map<ll,int> st; int main(){ int n; int i; cin>>n; for(i=1;i<=n;i++){ scanf("%d",&a[i]); s[i]=s[i-1]+a[i]; } int l=0,r=1; ll ans=0; st[0]=1; while(r<=n){ while(st[s[r]]){ st[s[l]]--; l++; } ans+=r-l; st[s[r]]++; r++; } cout<<ans<<endl; return 0; }
没有人不辛苦,只有人不喊疼