题目大意:
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=6345
求给定串到的位置里字典序最小的字串出现的次数。
思路:
字典序最小的串,肯定是一个字符啊。
可以用线段树维护一下。时间复杂度
当然也可以用前缀和。时间复杂度
代码:
线段树:
#include <cstdio>
#include <cstring>
#include <iostream>
#define N 1000100
using namespace std;
int n,t,m;
char c[N];
struct node
{
int l,r,sum;
char c;
}tree[N*3];
void make(int x) //建树
{
if (tree[x].l==tree[x].r)
{
tree[x].c=c[tree[x].l];
tree[x].sum=1;
return;
}
int mid=(tree[x].l+tree[x].r)/2;
tree[x*2].l=tree[x].l;
tree[x*2].r=mid;
tree[x*2+1].l=mid+1;
tree[x*2+1].r=tree[x].r;
make(x*2);
make(x*2+1);
if (tree[x*2].c==tree[x*2+1].c) //最小字符和出现次数更改
{
tree[x].c=tree[x*2].c;
tree[x].sum=tree[x*2].sum+tree[x*2+1].sum;
}
else if (tree[x*2].c<tree[x*2+1].c)
{
tree[x].c=tree[x*2].c;
tree[x].sum=tree[x*2].sum;
}
else
{
tree[x].c=tree[x*2+1].c;
tree[x].sum=tree[x*2+1].sum;
}
return;
}
int find(int x,int l,int r)
{
if (tree[x].l==l&&tree[x].r==r)
return tree[x].sum*100+(int)(tree[x].c-'A');
//这里用到了一些小技巧,本来要返回一个字符和出现次数的,但是我直接返回出现次数*100再加上字符的ASCII码值-A的ASCII码值
if (tree[x].l==tree[x].r)
return 0;
int mid=(tree[x].l+tree[x].r)/2;
if (r<=mid) return find(x*2,l,r);
if (l>mid) return find(x*2+1,l,r);
int a=find(x*2,l,mid);
int b=find(x*2+1,mid+1,r);
if (a%100<b%100) return a;
if (a%100>b%100) return b; //取出字符和ASCII码
return (a/100+b/100)*100+a%100; //更新
}
int main()
{
scanf("%d",&t);
int x,y;
for (int q=1;q<=t;q++)
{
scanf("%d%d",&n,&m);
cin>>c+1;
tree[1].l=1;
tree[1].r=n;
make(1);
printf("Case #%d:\n",q);
while (m--)
{
scanf("%d%d",&x,&y);
int a=find(1,x,y);
printf("%d\n",a/100);
}
}
return 0;
}
前缀和:
#include <cstdio>
#include <iostream>
#include <cstring>
#define N 1000100
using namespace std;
int s[N][30],t,n,m,l,r;
char c[N];
int main()
{
scanf("%d",&t);
for (int q=1;q<=t;q++)
{
memset(s,0,sizeof(s));
scanf("%d%d",&n,&m);
cin>>c+1;
for (int i=1;i<=n;i++)
s[i][c[i]-'A'+1]++;
for (int i=1;i<=n;i++)
for (int j=1;j<=26;j++)
s[i][j]+=s[i-1][j];
printf("Case #%d:\n",q);
while (m--)
{
scanf("%d%d",&l,&r);
for (int i=1;i<=26;i++)
if (s[r][i]-s[l-1][i])
{
printf("%d\n",s[r][i]-s[l-1][i]);
break;
}
}
}
return 0;
}