两个线段树是查询即可
#include <stdio.h>
#include <string.h>
#include <algorithm>
#define MAX 100000+10
using namespace std;
int ans[4*MAX];
char a[MAX];
int h[4*MAX][27];
void PushUp(int rt)//存入值
{
ans[rt]=min(ans[rt<<1],ans[rt<<1|1]);
for(int i=0;i<26;i++)
{
h[rt][i]=h[2*rt][i]+h[2*rt+1][i];
}
}
void Build(int l,int r,int rt)//建树
{
if(l==r)
{
ans[rt]=a[l];
h[rt][a[l]-'A']=1;
//printf("%c\n",a[l]);
return ;
}
int m=(l+r)>>1;
Build(l,m,rt<<1);
Build(m+1,r,rt<<1|1);
PushUp(rt);
}
int Query(int L,int R,int l,int r,int rt)//查询
{
if(L<=l&&r<=R)
{
return ans[rt];
}
int m=(l+r)>>1;
int ANS=99999;
if(L<=m)ANS=min(ANS,Query(L,R,l,m,rt<<1));
if(R>m)ANS=min(ANS,Query(L,R,m+1,r,rt<<1|1));
return ANS;
}
int Query_ans(int target,int L,int R,int l,int r,int rt)
{
if(L<=l&&r<=R)
{
return h[rt][target];
}
int m=(l+r)/2;
int ANS=0;
if(L<=m)ANS+=Query_ans(target,L,R,l,m,rt<<1);
if(R>m)ANS+=Query_ans(target,L,R,m+1,r,rt<<1|1);
return ANS;
}
int main(int argc, char *argv[])
{
int t;
int ca=1;
scanf("%d",&t);
while(t--)
{
int n,q,i,j;
memset(h,0,sizeof(h));
scanf("%d %d",&n,&q);
scanf("%s",a+1);
printf("Case #%d:\n",ca++);
Build(1,n,1);
while(q--)
{
int l,r;
scanf("%d %d",&l,&r);
int ans1=Query(l,r,1,n,1);
printf("%d\n",Query_ans(ans1-'A',l,r,1,n,1));
}
}
return 0;
}