题意:先给你一个字符串,然后对这个字符串有些操作,1 x a就是把x位置上的字符替换成a,2 x y就是问区间[x,y]上有多少个不同的字符;
用1<<(s[i]-‘a’)代表这个字符,用线段树去维护,注意是用|
#include <cstdio>
#include <algorithm>
#include <cstring>
#include <string>
#include <iostream>
using namespace std;
const int N = 1e5+10;
char s[N];
int q,op,l,r;
char ch;
struct Node{
int l,r,sum;
}tree[N<<2];
void build(int p,int l,int r){
tree[p].l = l,tree[p].r = r;
if(l==r){
tree[p].sum = 1<<(s[l]-'a');
return;
}
int mid = l+r>>1;
build(p<<1,l,mid);
build(p<<1|1,mid+1,r);
tree[p].sum = tree[p<<1].sum|tree[p<<1|1].sum;
}
void update(int p,int pos,int x){
int l = tree[p].l,r = tree[p].r;
if(l==r){
tree[p].sum = 1<<x;
return;
}
int mid = l+r>>1;
if(pos <= mid){
update(p<<1,pos,x);
}else update(p<<1|1,pos,x);
tree[p].sum = tree[p<<1].sum|tree[p<<1|1].sum;
}
int query(int p,int L,int R){
int l = tree[p].l,r = tree[p].r;
if(L<=l&&R>=r) return tree[p].sum;
int mid = l+r>>1;
int res = 0;
if(L <= mid) res|=query(p<<1,L,R);
if(R > mid) res|=query(p<<1|1,L,R);
return res;
}
int main(){
scanf("%s",s+1);
int n = strlen(s+1);
build(1,1,n);
scanf("%d",&q);
while(q--){
scanf("%d",&op);
if(op==1){
scanf("%d %c",&l,&ch);
update(1,l,ch-'a');
}else{
scanf("%d %d",&l,&r);
int res = query(1,l,r);
int ans = 0;
while(res){
if(res&1) ans++;
res>>=1;
}
printf("%d\n",ans);
}
}
return 0;
}