原题链接:https://codeforces.com/contest/1234/problem/D
单点修改,区间查询,几乎是线段树模板吧
树状数组应该也可以
就是每个节点维护其子节点的每个字母是否存在
代码:
#include <bits/stdc++.h>
#define ll long long
using namespace std;
struct node
{
int l,r;
int a[30];
}sum[400005];
int op=1,d[100005],e[30];
void build(int l,int r,int os)
{
sum[os].l=l;
sum[os].r=r;
if(l==r)
{
sum[os].a[d[op]]=1;
op++;
return;
}
int mid=(l+r)/2;
build(l,mid,os*2);
build(mid+1,r,os*2+1);
for(int i=0;i<26;i++)
{
if(sum[os*2].a[i]==1&&sum[os].a[i]==0)
{sum[os].a[i]=1;}
if(sum[os*2+1].a[i]==1&&sum[os].a[i]==0)
{sum[os].a[i]=1;}
}
}
void change(int x,int y,int z,int os)
{
if(x<=sum[os].l&&y>=sum[os].r)
{
for(int i=0;i<26;i++)
{sum[os].a[i]=0;}
sum[os].a[z]=1;
return;
}
int mid=(sum[os].l+sum[os].r)/2;
if(x<=mid)
{change(x,y,z,os*2);}
if(y>mid)
{change(x,y,z,os*2+1);}
for(int i=0;i<26;i++)
{
sum[os].a[i]=0;
if(sum[os*2].a[i]==1&&sum[os].a[i]==0)
{sum[os].a[i]=1;}
if(sum[os*2+1].a[i]==1&&sum[os].a[i]==0)
{sum[os].a[i]=1;}
}
}
void ask(int x,int y,int os)
{
if(x<=sum[os].l&&y>=sum[os].r)
{
for(int i=0;i<26;i++)
{
if(sum[os].a[i]==1&&e[i]==0)
{e[i]=1;}
}
return ;
}
int mid=(sum[os].l+sum[os].r)/2;
if(x<=mid)
{ask(x,y,os*2);}
if(y>mid)
{ask(x,y,os*2+1);}
}
int main()
{
int t,l,r,f,p;
char s[100005],c;
scanf("%s",s);
int len=strlen(s);
for(int i=1;i<=len;i++)
{d[i]=s[i-1]-'a';}
build(1,len,1);
scanf("%d",&t);
while(t--)
{
scanf("%d",&f);
if(f==1)
{
scanf("%d %c",&p,&c);
int u=c-'a';
change(p,p,u,1);
}
if(f==2)
{
int ans=0;
scanf("%d %d",&l,&r);
ask(l,r,1);
for(int i=0;i<26;i++){ans+=e[i];e[i]=0;}
printf("%d\n",ans);
}
}
return 0;
}