题目链接: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 ",temp); 101 } 102 } 103 return 0; 104 }