题目描述
You are given a string s consisting of lowercase Latin letters and q queries for this string.
Recall that the substring s[l;r] of the string s is the string slsl+1…sr. For example, the substrings of “codeforces” are “code”, “force”, “f”, “for”, but not “coder” and “top”.
There are two types of queries:
1 pos c (1≤pos≤|s|, c is lowercase Latin letter): replace spos with c (set spos:=c);
2 l r (1≤l≤r≤|s|): calculate the number of distinct characters in the substring s[l;r].
Input
The first line of the input contains one string s consisting of no more than 105 lowercase Latin letters.
The second line of the input contains one integer q (1≤q≤105) — the number of queries.
The next q lines contain queries, one per line. Each query is given in the format described in the problem statement. It is guaranteed that there is at least one query of the second type.
Output
For each query of the second type print the answer for it — the number of distinct characters in the required substring in this query.
Examples
Input
abacaba
5
2 1 4
1 4 b
1 5 b
2 4 6
2 1 7
Output
3
1
2
Input
dfcbbcfeeedbaea
15
1 6 e
1 4 b
2 6 14
1 7 b
1 12 c
2 6 8
2 1 6
1 7 c
1 2 f
1 10 a
2 7 9
1 10 a
1 14 b
1 1 f
2 1 11
Output
5
2
5
2
6
题目大意
给你一个字符串s,和q组询问/指令。
指令1:输入pos和字符c,然后将s中pos位置的字符改为c。
指令2:输入l和r,然后找出s的[l,r]区间中有多少种字符。
题目分析
快速的区间查询+修改,很容易就能想到树状数组,但是想到了树状数组这个题还是不太好做的。还有一个关键的问题是:怎么查询字符的种类。
我们可以用维护26个树状数组,每个树状数组只储存一种字符的情况,当查询时我们可以遍历26个数组的对于区间,看看该区间上是否存在该字符。
代码如下
#include <iostream>
#include <cstdio>
#include <cmath>
#include <string>
#include <cstring>
#include <stack>
#include <map>
#include <queue>
#include <vector>
#include <set>
#include <algorithm>
#include <iomanip>
#define LL long long
#define PII pair<int,int>
using namespace std;
const int N=1e5+5;
int len;
char s[N];
int tr[26][N];
int lowbit(int x)
{
return x & -x;
}
void add(int k,int x,int c) //k记录该字符对应哪一个树状数组,x记录位置
{
for(int i=x;i<=len;i+=lowbit(i))
tr[k][i]+=c;
}
int sum(int k,int x)
{
int res=0;
for(int i=x;i>0;i-=lowbit(i))
res+=tr[k][i];
return res;
}
int main()
{
scanf("%s",s+1);
len=strlen(s+1);
for(int i=1;i<=len;i++) //树状数组的建立,注意不同的字符要插入不同的数组中
add(s[i]-'a',i,1);
int q;
scanf("%d",&q);
while(q--)
{
int op;
scanf("%d",&op);
if(op==1) //修改操作
{
int pos;
char c;
scanf("%d %c",&pos,&c);
add(s[pos]-'a',pos,-1); //删去原来的字符
add(c-'a',pos,1); //添加新的字符
s[pos]=c; //修改字符串
}
else //查询操作
{
int l,r;
scanf("%d %d",&l,&r);
int res=0;
for(int i=0;i<26;i++) //如果该区间中某个字符的数量大于0,那么res++
if(sum(i,r)-sum(i,l-1)>=1) res++;
printf("%d\n",res);
}
}
return 0;
}