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;
}
View Code

 

posted @ 2020-04-15 14:10  朝暮不思  阅读(148)  评论(0编辑  收藏  举报