题面:cf814c
简要题意:给出串s,每次询问a,b,表示可以把s中的字母可以改动a次,求在s中能够构造出字母为b的最长连续子串
QAQ比赛的时候清零清错FST了QAQ
我们其实可以用一种离线的做法来做这题
我们把同一字母的询问归到一起,然后一起做掉
比如对于字母c,我们直接处理出对于c的一个数组p[i]表示最多改动i个字母成c后可以连出来最长的串
这样我们可以很快地扫一遍做出来,打个前缀
然后把一类字母的统计答案
这样时间复杂度还是有保证的(虽然我不会算)
然后。。。然后我p数组清空的时候忘记0这个位置了。。。
FST。。。QAQ
#include <cstdio>
#include <algorithm>
#include <cmath>
#include <cstring>
#include <iostream>
#include <ctime>
#include <map>
#include <queue>
#include <cstdlib>
#include <string>
#include <climits>
#include <set>
using namespace std;
struct ppap{int x,w;char c;}a[1000001];
inline bool cmp(ppap a,ppap b){return a.c<b.c;}
int n,m,ans[1000001],p[100001];
char s[100001];
inline void work(int x,char c){
for(int i=0;i<=n;i++)p[i]=0;//i从0开始!!!
for(int i=1;i<=n;i++){
int t=i,r=0,q=0;
while(t<=n){
if(s[t]!=c)r++;q++;t++;//p数组扫出来
p[r]=max(p[r],q);
}
}
for(int i=1;i<=n;i++)p[i]=max(p[i],p[i-1]);//前缀
for(int i=x;i<=m&&a[i].c==c;i++)ans[a[i].w]=p[a[i].x];//统计答案
}
int main()
{
scanf("%d",&n);scanf("%s",s+1);
scanf("%d",&m);
for(int i=1;i<=m;i++){
scanf("%d",&a[i].x);a[i].w=i;
char c[5];scanf("%s",c);a[i].c=c[0];
}
sort(a+1,a+m+1,cmp);//颜色归类
for(int i=1;i<=m;i++)if(i==1||a[i].c!=a[i-1].c)work(i,a[i].c);
for(int i=1;i<=m;i++)printf("%d\n",ans[i]);
return 0;
}