题目链接: Good Subarrays
大致题意
给定一个长度为n的序列, 问有多少个连续子序列满足 ∑ i = 1 n a i = r − l + 1 \displaystyle \sum_{i = 1}^na_i = r - l + 1 i=1∑nai=r−l+1.
解题思路
思维
我们考虑枚举右端点 r r r来计算答案:
设 [ l , r ] [l, r] [l,r]满足条件, 我们应该找到有多少个 l l l满足要求.
设 s [ ] s[] s[]为 a a a的前缀和数组, 则 [ 1 , r ] [1, r] [1,r]的和为 s [ r ] s[r] s[r], 我们希望 s [ r ] = r s[r] = r s[r]=r, 但是存在 q a q = s [ r ] − r qaq = s[r] - r qaq=s[r]−r的差值, 如果 [ 1 , p o s ] [1, pos] [1,pos]的区间和也为 q a q qaq qaq, 则 [ p o s + 1 , r ] [pos + 1, r] [pos+1,r]合法.
因此我们对于所有的位置记录一个 s [ i ] − i s[i] - i s[i]−i的差值即可.
特别的, 由于本身 s [ r ] = r s[r] = r s[r]=r的情况也是合法的, 我们应当初始化 m p [ 0 ] = 1 mp[0] = 1 mp[0]=1
AC代码
#include <bits/stdc++.h>
#define rep(i, n) for (int i = 1; i <= (n); ++i)
using namespace std;
typedef long long ll;
const int N = 1E5 + 10;
int a[N], s[N];
int main()
{
int t; cin >> t;
while (t--) {
int n; scanf("%d", &n);
rep(i, n) scanf("%1d", &a[i]), s[i] = s[i - 1] + a[i];
unordered_map<int, int> mp; mp[0] = 1;
ll res = 0;
rep(i, n) {
res += mp[s[i] - i];
mp[s[i] - i]++;
}
printf("%lld\n", res);
}
return 0;
}