题解:B4153 [厦门小学生 C++ 2022] 序列问题
CocoonBroken · · 题解
题意已经很简洁了不再赘述。
思路:
首先
考虑前缀和优化快速计算子串数量。因为子串
于是就可以记录出在此之前计算出的前缀和比当前的前缀和小的数量就行了。一开始用树状数组维护,但是发现时间复杂度还是有点高。
后来找了几个样例模拟发现,不需要把所有的比当前小的数都维护,可以一个一个传递下去。
设
比如当
然后就可以用一个数组记录
代码:
#include<bits/stdc++.h>
#define int long long
using namespace std;
const int N=1e7+5;
int n,res,num,ans;
char s[N];
int mp[N*2];
signed main(){
scanf("%lld",&n);
scanf("%s",s+1);
mp[n]=1;
for(int i=1;i<=n;i++){
ans+=s[i]=='1'?mp[n+num]:-mp[n+num-1];
num+=s[i]=='1'?1:-1;
mp[n+num]++,res+=ans;
}printf("%lld",res);
return 0;
}