P16592 [GKS 2016 #E] Diwali lightings 题解
题目大意
给你一个由字符 B 和 R 的组成的字符串 \(S\),设由无数个字符串 \(S\) 连接组成的字符串为 \(Z\),问从第 \(I\) 个字符到第 \(J\) 个字符中有几个 B。
思路分析
多组询问、求区间和,这一看就是前缀和。但是如果硬枚举的话,肯定会超时。
既然字符串 \(Z\) 是由无数个字符串 \(S\) 连接组成的,那么肯定会有很多重复的部分。
而这段重复的部分显然可以不用一个一个算,而是算出其中一个的目标字符的数量,然后乘上出现的完整周期数量,再加上剩余的字符里出现目标字符的次数,这就是算一个前缀里目标字符出现次数的方法。
算区间和用前缀和的原理算就行了。
#include<bits/stdc++.h>
using namespace std;
string s;
long long ans=0,num=0,n;//不开longlong___
long long getans(long long x){//求前缀和
long long anss=x/n*num;//完整周期数量
for(int i=1;i<=x%n;i++){//剩余的
anss+=(s[i]=='B');
}
return anss;
}
int main(){
std::ios::sync_with_stdio(0);
cin.tie(0),cout.tie(0);
int T;
cin>>T;
for(int id=1;id<=T;id++){
ans=num=0;
long long I,J;
cin>>s>>I>>J;
n=s.size();
s=" "+s;
for(int i=1;i<=n;i++){
if(s[i]=='B')num++;//统计一个周期的目标字符数量
}
long long r=getans(J),l=getans(I-1);
cout<<"Case #"<<id<<": "<<r-l<<'\n';//前缀和
}
return 0;
}

浙公网安备 33010602011771号