Codeforces Round #423 (Div. 1, rated, based on VK Cup Finals)
B. High Load
题意:给定一个只包含A,T,C,G的字符串S,有如下两种操作
1)修改一个点的字母.
2)给定一个字符串e ($left | e ight |leq 10$),生成一个由e重复组成的新串,eee...,问$S_{l..r}$中有几个字母跟这个新的字符串一一对应。
SOL:对于每个字母,用BIT[x][y][L]表示$S_{1..L}$中,所有$equiv xleft (mod \, y ight )$的位置出现了该字母几次。然后复杂度大概就是$O(100*mlogn)$。
然而比赛的时候由于没有想到树状数组动态更新前缀和,而是用了一个静态数组,强行用定期重构过去了。。复杂度$O(10 * m*sqrt{n})$,略微有些暴力。
1 #include <set> 2 #include <cmath> 3 #include <cstdio> 4 #include <cstring> 5 #include <iostream> 6 #include <algorithm> 7 using namespace std; 8 const int LEN = 1e5 + 5; 9 int i, j, k, n, m, s, t, ans, S, top; 10 char c[LEN], a[LEN], d[LEN]; 11 int f[LEN][15][4]; 12 set <int> st; 13 typedef set <int> :: iterator iter; 14 const char to[4] = {'A', 'C', 'G', 'T'}; 15 int get(char x) { 16 if (x == 'A') { 17 return 0; 18 } else if (x == 'C') { 19 return 1; 20 } else if (x == 'G') { 21 return 2; 22 } else { 23 return 3; 24 } 25 } 26 void init() { 27 for (int i = n; i >= 1; i--) { 28 for (int j = 1; j <= 10; j++) { 29 for (int k = 0; k < 4; k++) { 30 if (get(c[i]) == k) { 31 f[i][j][k] = 1; 32 } else { 33 f[i][j][k] = 0; 34 } 35 if (i + j <= n) { 36 f[i][j][k] += f[i + j][j][k]; 37 } 38 } 39 } 40 } 41 } 42 int ask(int l, int r, int L) { 43 int ans = 0; 44 if (r - l + 1 <= L) { 45 for (int i = l; i <= r; i++) { 46 if (c[i] == a[i - l + 1]) { 47 ans++; 48 } 49 } 50 } else { 51 for (int i = 1; i <= L; i++) { 52 int t = get(a[i]); 53 ans += f[l + i - 1][L][t]; 54 int k = (r - l + 1 - i) / L + 1; 55 if (k >= 0 && l + i - 1 + k * L <= n) { 56 ans -= f[l + i - 1 + k * L][L][t]; 57 } 58 } 59 } 60 for (iter it = st.begin(); it != st.end(); it++) { 61 int x = *it, t = get(d[x]); 62 if (l <= x && x <= r) { 63 int p = (x - l) % L + 1; 64 if (get(c[x]) == get(a[p]) && get(a[p]) != t) { 65 ans--; 66 } 67 if (get(c[x]) != get(a[p]) && get(a[p]) == t) { 68 ans++; 69 } 70 } 71 } 72 return ans; 73 } 74 void rebuild() { 75 for (iter p = st.begin(); p != st.end(); p++) { 76 int x = *p; 77 c[x] = d[x]; 78 } 79 init(); 80 st.clear(); 81 } 82 int main() { 83 scanf("%s", c + 1); 84 n = strlen(c + 1); 85 S = sqrt(n) + 200; 86 init(); 87 scanf("%d", &m); 88 while (m--) { 89 int op, l, r; 90 scanf("%d", &op); 91 if (op == 2) { 92 scanf("%d %d", &l, &r); 93 scanf("%s", a + 1); 94 int L = strlen(a + 1); 95 printf("%d ", ask(l, r, L)); 96 } else { 97 scanf("%d %s", &l, a + 1); 98 st.insert(l); 99 d[l] = a[1]; 100 if (st.size() >= S) { 101 rebuild(); 102 } 103 } 104 } 105 return 0; 106 }