Description
给出一个长度为n的序列a,问有多少连续子段的和为s
Input
第一行两整数n和s分别表示序列长度和目标子段和,之后n个整数a[i] (1<=n<=200000,-2e14<=s<=2e14,-1e9<=a[i]<=1e9)
Output
输出连续子段和为s的子段数量
Sample Input
5 2
-1 1 2 -1 1
Sample Output
5
Solution
用map记一下前缀和sum[i],每次固定子段左端点i后查询sum[i]+s的数量即为满足该左端点i的右端点数量,注意查询i前要先把sum[i]的数量减一(否则s=0时会记重)
Code
#include<cstdio>
#include<iostream>
#include<cstring>
#include<algorithm>
#include<cmath>
#include<vector>
#include<queue>
#include<map>
#include<set>
#include<ctime>
using namespace std;
typedef long long ll;
#define INF 0x3f3f3f3f
#define maxn 222222
int n;
ll s,sum[maxn];
map<ll,int>m;
int main()
{
while(~scanf("%d%I64d",&n,&s))
{
m.clear();
sum[0]=0;
m[0]++;
for(int i=1;i<=n;i++)
{
scanf("%I64d",&sum[i]);
sum[i]+=sum[i-1];
m[sum[i]]++;
}
ll ans=0;
for(int i=0;i<n;i++)
{
m[sum[i]]--;
ans+=m[sum[i]+s];
}
printf("%I64d\n",ans);
}
return 0;
}