今天下午打球了,没写题,晚上来写了两道,一道数学一道小思维
题目:https://codeforces.com/problemset/problem/1398/C
题目大意:求一个数组的子数组所有元素和等于子数组长度的数量。
数据量1e5,不能暴力,应该是前缀和。
由于子数组和为长度,那么所有元素减1后,子数组元素和都为零,原来可能是1~n,状态减少了,
我们想如果一个子数组和为0,那么在前缀和数组里表现为有两个数相等,表示他们两个之间的区间和为0,
所以用map统计所有前缀和出现的次数,再计算就行了,注意0的特判,因为0的长度可以是1。
代码:
include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N = 200010;
void solve()
{
int n;
cin >> n;
string s;
cin >> s;
map<ll,ll> mp;
ll sum = 0;
ll ans = 0;
for(int i = 0;i<n;i++)
{
sum += s[i] - '0' - 1;
if(sum == 0) ans ++;
ans += mp[sum];
mp[sum] ++;
}
cout << ans << endl;
}
int main()
{
int t;
cin >> t;
while(t--)
{
solve();
}
return 0;
}