C. Good Subarrays

传送门

分析

有点可惜,这道题原本可以A掉的,但是比赛的时候开的int答案溢出了

填空题:不开____见祖宗

这道题我一开始的思路是尺取加前缀和,被T掉了,后来观察这个数据范围大概知道这是个O(n)的做法

首先我们需要将每一位上数字-1,这样就可以把这个问题转换为求区间和为0的问题了
我们需要维护一个前缀和,当我们计算到第i位的时候,假设前缀和为x,如果x为0的话,答案可以+1,并且如果前面有一段前缀和为0的话,减去这一段也可以做到区间和为0,所以加上前面前缀和为0出现的次数

如果前缀和不为0,那么我们只需要减去一段区间和为x的区间就可以了

所以我们只需要维护一下第i位前面的前缀和,用map存一下就可以了

最后记得注意一下答案范围就好了

代码

#include <iostream>
#include <cstdio>
#include <cmath>
#include <algorithm>
#include <queue>
#include <cstring>
#include <unordered_map>
#define debug(x) cout<<#x<<":"<<x<<endl;
#define _CRT_SECURE_NO_WARNINGS
#pragma GCC optimize("Ofast","unroll-loops","omit-frame-pointer","inline")
#pragma GCC option("arch=native","tune=native","no-zero-upper")
#pragma GCC target("avx2")
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
int T;
typedef pair<int,ll> PII;
const int INF = 0x3f3f3f3f;
const int N = 5e4 + 10;



int main(){
    scanf("%d",&T);
    while(T--){
        unordered_map<int,int> M;
        int n;
        scanf("%d",&n);
        string str;
        cin >> str;
        ll ans = 0;
        int sum = 0;
        int x;
        for(int i = 1;i <= n;i++){
            x = str[i - 1] - '0' - 1;
            sum += x;
            if(sum == 0) ans++;
            ans += M[sum];
            M[sum]++;
        }
        
        printf("%lld\n",ans);
    }
    
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值