题目链接:简单子段和 - 题目 - Daimayuan Online Judge
题目描述
给出一个长为 N 的整数数组 A 和一个整数 K。
请问有数组 A 中有多少个子数组,其元素之和为 K?
输入格式
第一行两个整数 N 和 K,表示数组 A 的大小,和给出的整数 K。
第二行 N 个整数,表示数组 A 中的每个元素 A1,...,An。
输出格式
输出一个整数,表示答案。
样例输入1
6 5
8 -3 5 7 0 -4
样例输出1
3
有三个子数组 (A1,A2),(A3),(A2,...,A6)满足条件。
数据规模
对于全部数据保证 1≤N≤2×10^5,|Ai|≤10^9,|k|≤10^15。
求多少个子数组(连续)的和为k,预处理前缀和+map计数查询。对每个a[i](前缀和数组)找在i之后有多少个a[i]+k,即有多少子数组前缀和为k。那么怎么处理不会找到i前面的a[i]+k呢?在每次查询完将a[i]的数量-1.
详见代码:
#include <bits/stdc++.h>
using namespace std;
#define ll long long //数据很大会爆int
ll n, k, a[200009], ans; // a为前缀和数组
map<ll, int> mp; // mp记录某个值的数量
int main()
{
scanf("%lld%lld", &n, &k);
for (int i = 1; i <= n; i++)
{
ll x;
scanf("%lld", &x);
a[i] = a[i - 1] + x; //前缀和
mp[a[i]]++; //计数
}
for (int i = 1; i <= n; i++) //查询从i位置开始的子数组满足要求的个数
{
ll temp = a[i - 1] + k;
if (mp.find(temp) != mp.end())
{
ans += mp[temp];
}
mp[a[i]]--; //避免在后面查找a[i]+k的时候找到i前面的值
}
cout << ans;
}