Codeforces 1398C- Good Subarrays(区间值为0的个数变形-思维)

题目链接:https://codeforces.com/problemset/problem/1398/C
博客园食用链接: https://www.cnblogs.com/lonely-wind-/p/13509265.html

You are given an array a 1 , a 2 , … , a n a_1,a_2,…,a_n a1,a2,,an consisting of integers from 0 to 9. A subarray a l , a l + 1 , a l + 2 , … , a r − 1 a_l,a_{l+1},a_{l+2},…,a_{r−1} al,al+1,al+2,,ar1,ar is good if the sum of elements of this subarray is equal to the length of this subarray ∑ i = l r a i = r − l + 1 \sum_{i=l}^ra_i=r-l+1 i=lrai=rl+1.

For example, if a=[1,2,0], then there are 3 good subarrays: a 1 … 1 = [ 1 ] , a 2 … 3 = [ 2 , 0 ] a_{1…1}=[1],a_{2…3}=[2,0] a11=[1],a23=[2,0] and a 1 … 3 = [ 1 , 2 , 0 ] a_{1…3}=[1,2,0] a13=[1,2,0].

Calculate the number of good subarrays of the array a.

Input
The first line contains one integer t (1≤t≤1000) — the number of test cases.

The first line of each test case contains one integer n ( 1 ≤ n ≤ 1 0 5 ) n (1≤n≤10^5) n(1n105) — the length of the array a.

The second line of each test case contains a string consisting of n decimal digits, where the i-th digit is equal to the value of a i a_i ai.

It is guaranteed that the sum of n over all test cases does not exceed 1 0 5 10^5 105.

Output
For each test case print one integer — the number of good subarrays of the array a.

input
3
3
120
5
11011
6
600005
output
3
6
1

Note
The first test case is considered in the statement.

In the second test case, there are 6 good subarrays: a 1 … 1 , a 2 … 2 , a 1 … 2 , a 4 … 4 , a 5 … 5 a_{1…1}, a_{2…2}, a_{1…2}, a_{4…4}, a_{5…5} a11,a22,a12,a44,a55 and a 4 … 5 a_{4…5} a45.

In the third test case there is only one good subarray: a 2 … 6 a_{2…6} a26.

题目大意:给你一个字符串序列,你需要找到有多少个区间使得其区间内每个元素的和为区间长度。

emmm,对于其公式我们很容易看出其区间的平均值为1,我们将其每个数-1,就可变为另一个东西:求区间和值为0的有多少个。那么我们只需要记录其每个前缀和出现的次数就好了,也就是说对于一个前缀和,如果它第二次出现了,那么可以说明中间一定有存在构成一个0的区间。那么我们只需要将其每次出现的次数加上就好了。

以下是AC代码:

#include <bits/stdc++.h>
using namespace std;

typedef long long ll;
const int mac=1e5+10;

char s[mac];
int a[mac],sum[mac];

int main(int argc, char const *argv[])
{
	int t;
	scanf ("%d",&t);
	while (t--){
		int n;
		scanf ("%d",&n);
		scanf ("%s",s+1);
		for (int i=1; i<=n; i++)
			a[i]=s[i]-'0'-1,sum[i]=sum[i-1]+a[i];
		unordered_map<int,int>mp;
		ll ans=0;
		mp[0]=1;
		for (int i=1; i<=n; i++){
			if (mp[sum[i]]) ans+=mp[sum[i]],mp[sum[i]]++;
			else mp[sum[i]]++;
		}
		printf ("%lld\n",ans);
	}
	return 0;
}
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值