这个问题的意思就是让你找到一个区间内所有元素和等于区间长度的区间数量。
我们可以先把所有元素先减去1,这样得到的符合条件的区间内元素和0,题意也就变成了找所有和为0区间的数量。若采取暴力做法,题目数据是1e5,时间复杂度是O(n*n)会超时。这时候就要用到stl中的map来优化。
如果两个前缀和相等,则说明这两个前缀和之间的元素和为零,其中所有和为零的区间数为n*(n-1)/2,这里要给前缀和为0的一个特判,前缀和为零的有几个就说明有几个数为0,只需直接先将map[0]加一即可。用map来记各个前缀和的数量非常方便快捷。由于数据范围较大,这题答案要用longlong 类型,得出答案的表达式中的n也要用longlong 不然会超int范围导致答案错误。
代码如下:
#include<bits/stdc++.h>
using namespace std;
const int N = 100010;
typedef long long ll;
map<ll,ll> m;
int s[N];
int t;
ll ans;
int main()
{
cin >> t;
while(t --)
{
ans = 0;
int n;
cin >> n;
string str;
cin >> str;
for(int i = 1; i <= n; i ++) s[i] = s[i - 1] + str[i - 1] - '1';
m[0] ++;
for(int i = 1; i <= n; i ++) m[s[i]] ++;
for(auto it : m)
{
ans += it.second * (it.second - 1)/2;
}
printf("%lld\n", ans);
m.clear();
}
return 0;
}