题目链接:http://codeforces.com/problemset/problem/1234/D
题意:可修改某个字符,求区间字符种类有几种;
解题思路:明显的线段树区间和问题,把每个字母单独一个变量,每个节点就有26个计算出现数量即可,为0表示没有,最后遍历查询节点的26个字母出现情况,就是答案。
ac代码:
#include <cstdio>
#include <cstring>
#include <vector>
#include <iostream>
#include <algorithm>
#include <string>
#include <math.h>
#include <set>
#include <iterator>
#define inf 0x3f3f3f3f3f3f3f3f
#define lc (d<<1)
#define rc (d<<1|1)
#define mid ((l+r)>>1)
using namespace std;
typedef long long ll;
const int mx = 2e5+10;
const ll mod = 1e9+7;
char s[mx];
namespace T {
struct tree {
int a[27];
tree operator+(const tree &t) {
tree ts;
for (int i = 0; i < 26; ++i) {
ts.a[i] = a[i]+t.a[i];
}
return ts;
}
}T[mx*4];
void pushup(int d) {
T[d] = T[lc]+T[rc];
}
void build(int l, int r, int d) {
if (l == r) {
T[d].a[s[l]-'a']++;
return;
}
build(l, mid, lc);
build(mid+1, r, rc);
pushup(d);
}
void update(int l, int r, int d, int pos, char x) {
if (l == r) {
T[d].a[s[l]-'a']--;
s[l] = x;
T[d].a[x-'a']++;
return;
}
if (mid >= pos) update(l, mid, lc, pos, x);
else update(mid+1, r, rc, pos, x);
pushup(d);
}
tree Query(int l, int r, int d, int L, int R) {
if (l == L && r == R)
return T[d];
if (R <= mid) return Query(l, mid, lc, L, R);
if (L > mid) return Query(mid+1, r, rc, L, R);
return Query(l, mid, lc, L, mid)+Query(mid+1, r, rc, mid+1, R);
}
}
int main()
{
int n, a, b, c;
char x;
scanf("%s", s+1);
int len = strlen(s+1);
T::build(1, len, 1);
scanf("%d", &n);
for (int i = 0; i < n; ++i) {
scanf("%d", &a);
if (a == 1) {
scanf("%d %c", &b, &x);
T::update(1, len, 1, b, x);
}
else {
scanf("%d%d", &b, &c);
T::tree t = T::Query(1, len, 1, b, c);
int k = 0;
for (int i = 0; i < 26; ++i) {
if (t.a[i]) k++;
}
printf("%d\n", k);
}
}
return 0;
}