一道看似小学生的题,搞了我几个小时…
首先思路就有两种:
Ⅰ . 找 和 为 0 的 b a d 子 串 , 再 用 n ∗ ( n + 1 ) / 2 − b a d 子 串 得 到 答 案 Ⅰ.找和为0的bad子串,再用n*(n+1)/2-bad子串得到答案 Ⅰ.找和为0的bad子串,再用n∗(n+1)/2−bad子串得到答案
Ⅱ . 找 和 不 为 0 的 g o o d 子 串 Ⅱ.找和不为0的good子串 Ⅱ.找和不为0的good子串
如果你选择找bad子串就很麻烦了。(为什么呢?自己去试一试吧,不好说。)
这里找good子串,枚举每一个数作为区间的右端点。
那 么 往 左 找 一 个 前 缀 和 为 0 的 左 端 点 , 答 案 贡 献 就 是 i − l + 1 那么往左找一个前缀和为0的左端点,答案贡献就是i-l+1 那么往左找一个前缀和为0的左端点,答案贡献就是i−l+1
特 殊 的 , 对 于 第 一 个 前 缀 和 为 0 的 要 特 判 。 特殊的,对于第一个前缀和为0的要特判。 特殊的,对于第一个前缀和为0的要特判。
#include
using namespace std;
typedef long long ll;
const int maxn=2e5+9;
ll n,a[maxn],sumn,ans,L=0;
mapm;
int main()
{
cin>>n;
int flag=0;
m[0]=0;
for(int i=1;i<=n;i++)
{
scanf("%lld",&a[i]);
sumn+=a[i];
if(m[sumn]) L=max(L,m[sumn]+1);
else if(sumn==0)//特判,也要更新
L=max(L,(ll)1);
ans+=i-L;
m[sumn]=i;
}
cout<