题意:
给定一个字符串,可以进行两种操作:
- 1 pos c(1≤pos≤|s|, c是一个小写英文字母): 将第pos位换成c;
- 2 l r(1≤l≤r≤|s|): 查找从l到r中不同字符的个数.
只对第二种情况输出结果。
思路:
用26位二进制表示26个英文字母,使用线段树进行或运算。
#include<bits/stdc++.h>
using namespace std;
int d[400000];
char a[100010];
void build(int l,int r,int p){
if(l==r)d[p]=1<<(a[l-1]-'a');
else{
int m=(l+r)>>1;
build(l,m,p<<1);
build(m+1,r,p<<1|1);
d[p]=d[p<<1]|d[p<<1|1];
}
}
void update(int x,int y,int l,int r,int p){
if(l==r)d[p]=y;
else{
int m=(l+r)>>1;
if(x<=m)update(x,y,l,m,p<<1);
else update(x,y,m+1,r,p<<1|1);
d[p]=d[p<<1]|d[p<<1|1];
}
}
int query(int x,int y,int l,int r,int p){
if(x<=l&&r<=y)return d[p];
int m=(l+r)>>1,res=0;
if(x<=m)res|=query(x,y,l,m,p<<1);
if(y>m)res|=query(x,y,m+1,r,p<<1|1);
return res;
}
int main(){
scanf("%s",a);
int n=strlen(a);
build(1,n,1);
int q,x,y;
char z;
scanf("%d",&q);
while(q--){
scanf("%d",&x);
if(x==1){
scanf("%d %c",&y,&z);
update(y,1<<(z-'a'),1,n,1);
}else{
scanf("%d %d",&x,&y);
int ans=0,res=query(x,y,1,n,1);
while(res){
if(res&1){
ans++;
}
res/=2;
}
printf("%d\n",ans);
}
}
return 0;
}