题目链接:点击打开链接
题目大意:给定一个区间,求在这个区间中最小的字符char个数是多少。
解题思路:差分前缀和版 + 树状数组版。
AC 代码(差分前缀和)
#include<bits/stdc++.h>
#include<cmath>
#define mem(a,b) memset(a,b,sizeof a);
#define INF 0x3f3f3f3f
using namespace std;
typedef long long ll;
int a[100005][26];
char s[100005];
int main()
{
int T; scanf("%d",&T);
int n,q,l,r,kase=1;
while(T-- && ~scanf("%d%d",&n,&q))
{
mem(a,0);
scanf("%s",s);
int len=strlen(s);
a[0][s[0]-'A']++;
for(int i=1;i<len;i++)
{
a[i][s[i]-'A']++;
for(int j=0;j<26;j++)
a[i][j]+=a[i-1][j];
}
printf("Case #%d:\n",kase++);
while(q--)
{
scanf("%d%d",&l,&r);
int rs=0;
for(int i=0;i<26;i++)
{
if(a[r-1][i]>a[l-1-1][i])
{
rs=a[r-1][i]-a[l-1-1][i]; break;
}
}
printf("%d\n",rs);
}
}
return 0;
}
AC 代码(树状数组)
#include<bits/stdc++.h>
#include<cmath>
#define mem(a,b) memset(a,b,sizeof a);
#define INF 0x3f3f3f3f
using namespace std;
typedef long long ll;
const int maxn=1e5+10;
int n,q,T,kase=1;
int rs1[maxn]; // 记录最小值
int rs2[maxn][26]; // 前缀和
char s[maxn];
int lowbit(int x)
{
return x & -x;
}
void update_min_cnt(int x,int val)
{
while(x<=n)
{
rs1[x]=min(rs1[x],val);
rs2[x][val]++;
x+=lowbit(x);
}
}
int query_min(int l,int r)
{
int ans=s[r]-'A';
while(l!=r)
{
for(r--;r-lowbit(r)>=l;r-=lowbit(r))
ans=min(ans,rs1[r]);
ans=min(ans,s[r]-'A');
}
return ans;
}
int query_cnt(int l,int r)
{
int val=query_min(l,r);
int ans1=0,ans2=0;
while(r>0)
{
ans1+=rs2[r][val];
r-=lowbit(r);
}
r=l-1;
while(r>0)
{
ans2+=rs2[r][val];
r-=lowbit(r);
}
return ans1-ans2;
}
int main()
{
scanf("%d",&T);
while(T-- && ~scanf("%d%d",&n,&q))
{
printf("Case #%d:\n",kase++);
scanf("%s",s+1);
int len=strlen(s+1);
mem(rs1,INF); mem(rs2,0);
for(int i=1;i<=len;i++)
update_min_cnt(i,s[i]-'A');
int l,r;
while(q--)
{
scanf("%d%d",&l,&r);
// printf("%c\n",char(query_min(l,r)+'A'));
printf("%d\n",query_cnt(l,r));
}
}
return 0;
}
/*
10
9 3
ABEBBDCFC
3 7
1 1
1 6
*/