题目链接:https://codeforces.com/contest/1234/problem/D
题意:
给一个字符串s,存在两种操作
操作1:将某一位的字符改成给定的一个字符
操作2:询问一段区间内不同字符的个数
思路:
线段树维护各个区间的字符。然后查询的时候新开一个 数组t 去记录不同的字符
最后统计 t中字符的个数就可以了
不知道为什么我用set 和 string 就TLE 了
1 #include <math.h>
2 #include <stdio.h>
3 #include <iostream>
4 #include <algorithm>
5 #include <string>
6 #include <string.h>
7 #include <vector>
8 #include <map>
9 #include <stack>
10 #include <set>
11 #include <random>
12
13
14 #define LL long long
15
16 const int maxn = 2e5 + 10;
17
18
19 char s[maxn];
20 int tree[26][maxn<<2];
21 int t[26];
22
23
24 void pushup(int nod) {
25 for (int i=0;i<26;i++) {
26 tree[i][nod] = tree[i][nod<<1] | tree[i][(nod<<1)+1];
27 }
28 }
29
30 void build(int l,int r,int nod) {
31 if (l == r) {
32 tree[s[l]-'a'][nod] = 1;
33 return ;
34 }
35 int mid = (l + r ) >> 1;
36 build(l,mid,nod<<1);
37 build(mid+1,r,(nod<<1)+1);
38 pushup(nod);
39 }
40
41 void modify(int l,int r,int k,int pos,int v) {
42 if (l == r) {
43 for (int i=0;i<26;i++) {
44 tree[i][k] = 0;
45 }
46 tree[v][k] = 1;
47 return ;
48 }
49 int mid = (l + r) >> 1;
50 if (pos <= mid) {
51 modify(l,mid,k<<1,pos,v);
52 } else {
53 modify(mid+1,r,(k<<1)+1,pos,v);
54 }
55 pushup(k);
56 }
57
58 void query(int L,int R,int l,int r,int k) {
59 if (L <= l && R >= r) {
60 for (int i=0;i<26;i++) {
61 t[i] |= tree[i][k];
62 }
63 return ;
64 }
65 int mid = (l + r) >> 1;
66 if (L <= mid) {
67 query(L,R,l,mid,k<<1);
68 }
69 if (R > mid) {
70 query(L,R,mid+1,r,(k<<1)+1);
71 }
72 }
73
74
75
76 int main() {
77 std::cin >> s+1;
78 int n = strlen(s+1);
79 int T;
80 int opt,x,y;
81 char z;
82 std::cin >> T;
83 build(1,n,1);
84 while (T--) {
85 std::cin >> opt;
86 if (opt == 1) {
87 std::cin >> x >> z;
88 modify(1,n,1,x,z-'a');
89 }
90 else if (opt == 2) {
91 int temp = 0;
92 std::cin >> x >> y;
93 query(x,y,1,n,1);
94 for (int i=0;i<26;i++) {
95 if (t[i]) {
96 ++temp;
97 t[i] = 0;
98 }
99 }
100 printf("%d\n",temp);
101 }
102 }
103 return 0;
104 }
知识兔