Good Subarrays(前缀和)

本文探讨了如何解决一个特定的数学问题:给定一系列数字,找出所有连续子区间,其元素之和等于子区间的长度。通过巧妙地转换问题,并使用前缀和的概念,我们提出了一种高效的算法解决方案。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

题目
题意:给定n个数,每个数大小为0-9,求这n个数,有多少个连续子区间,满足 ∑ i = l r = = ( r − l + 1 ) \sum_{i=l}^{r}==(r-l+1) i=lr==(rl+1)

思路:每个数都减去1,问题转化为,求有有多少个连续子区间,满足 ∑ i = l r = = 0 \sum_{i=l}^{r}==0 i=lr==0,只需求出每个前缀和,如果 s u m i = 1 l = = s u m i = 1 r sum_{i=1}^l == sum_{i=1}^r sumi=1l==sumi=1r,说明 s u m i = l + 1 r = = 0 sum_{i=l+1}^{r} == 0 sumi=l+1r==0。因此,找出所有前缀和相同的个数x,那么这些前缀和贡献的区间数为 x ∗ ( x − 1 ) / 2 x*(x-1)/2 x(x1)/2,注意,初始时, n u m 0 = 1 num_0=1 num0=1

#include<bits/stdc++.h>
using namespace std;
#define ll long long
const int maxn = 100010;

int a[maxn];
char s[maxn];
int n;
unordered_map<int, int> mp;

int main() {
    int t;
    scanf("%d", &t);
    while(t--) {
        scanf("%d", &n);
        scanf("%s", s);
        a[0] = 0;
        mp.clear();
        ++mp[0];// 初始时,mp[0]=1
        for(int i = 1;i <= n; ++i) {
            a[i] = a[i-1] + s[i-1] - '0' - 1;
            ++mp[a[i]];
        }
        ll ans = 0;
        for(auto it: mp) {
            ans += 1LL * it.second * (it.second - 1) / 2;
        }
        printf("%lld\n", ans);
    }
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值