#include <cstdio> #include <algorithm> #warning change the size of arrays using namespace std; const long long mod = 1'000'000'007; const int MAX_N = 300'000; char c[MAX_N]; int n, q; const int leaf_count = 1 << 18; int tree[leaf_count * 2][3]; int cnt[256][2]; void merge_sons(int x) { fill(tree[x], tree[x] + 3, 0); for(int i = 0; i < 3; i++) { for(int j = 0; j < 3; j++) { tree[x][(i + j) % 3] += 1ll * tree[x * 2][i] * tree[x * 2 + 1][j] % mod; if(tree[x][(i + j) % 3] >= mod) tree[x][(i + j) % 3] -= mod; } } } void build_tree() { for(int i = 0; i < n; i++) cnt[c[i]][i % 2]++; for(int i = 0; i < leaf_count * 2; i++) fill(tree[i], tree[i] + 3, 0); for(int i = leaf_count; i < leaf_count + n; i++) { switch(c[i - leaf_count]) { case 'C': tree[i][1] = 1; break; case 'Z': tree[i][2] = 1; break; case 'N': tree[i][1] = tree[i][2] = 1; break; } } for(int i = n + leaf_count; i < leaf_count * 2; i++) tree[i][0] = 1; for(int i = leaf_count - 1; i > 0; i--) merge_sons(i); } void update(int x, char t) { cnt[c[x]][x % 2]--; c[x] = t; cnt[c[x]][x % 2]++; x += leaf_count; fill(tree[x], tree[x] + 3, 0); switch(t) { case 'C': tree[x][1] = 1; break; case 'Z': tree[x][2] = 1; break; case 'N': tree[x][1] = tree[x][2] = 1; break; } for(x /= 2; x; x /= 2) merge_sons(x); } int get_answer() { if(n == 1) { if(c[0] == 'N') return 2; return 1; } int answer = tree[1][1] + tree[1][2]; if(answer >= mod) answer -= mod; if(n % 2 == 1) { for(int j = 0; j < 2; j++) if(cnt['C'][j ^ 0] == 0 && cnt['Z'][j ^ 1] == 0) answer -= 1; if(answer < 0) answer += mod; } return answer; } int main() { scanf("%d%d", &n, &q); scanf("%s", c); build_tree(); printf("%d\n", get_answer()); while(q--) { int x; scanf("%d", &x); char t; scanf(" %c", &t); update(x - 1, t); printf("%d\n", get_answer()); } return 0; }
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 | #include <cstdio> #include <algorithm> #warning change the size of arrays using namespace std; const long long mod = 1'000'000'007; const int MAX_N = 300'000; char c[MAX_N]; int n, q; const int leaf_count = 1 << 18; int tree[leaf_count * 2][3]; int cnt[256][2]; void merge_sons(int x) { fill(tree[x], tree[x] + 3, 0); for(int i = 0; i < 3; i++) { for(int j = 0; j < 3; j++) { tree[x][(i + j) % 3] += 1ll * tree[x * 2][i] * tree[x * 2 + 1][j] % mod; if(tree[x][(i + j) % 3] >= mod) tree[x][(i + j) % 3] -= mod; } } } void build_tree() { for(int i = 0; i < n; i++) cnt[c[i]][i % 2]++; for(int i = 0; i < leaf_count * 2; i++) fill(tree[i], tree[i] + 3, 0); for(int i = leaf_count; i < leaf_count + n; i++) { switch(c[i - leaf_count]) { case 'C': tree[i][1] = 1; break; case 'Z': tree[i][2] = 1; break; case 'N': tree[i][1] = tree[i][2] = 1; break; } } for(int i = n + leaf_count; i < leaf_count * 2; i++) tree[i][0] = 1; for(int i = leaf_count - 1; i > 0; i--) merge_sons(i); } void update(int x, char t) { cnt[c[x]][x % 2]--; c[x] = t; cnt[c[x]][x % 2]++; x += leaf_count; fill(tree[x], tree[x] + 3, 0); switch(t) { case 'C': tree[x][1] = 1; break; case 'Z': tree[x][2] = 1; break; case 'N': tree[x][1] = tree[x][2] = 1; break; } for(x /= 2; x; x /= 2) merge_sons(x); } int get_answer() { if(n == 1) { if(c[0] == 'N') return 2; return 1; } int answer = tree[1][1] + tree[1][2]; if(answer >= mod) answer -= mod; if(n % 2 == 1) { for(int j = 0; j < 2; j++) if(cnt['C'][j ^ 0] == 0 && cnt['Z'][j ^ 1] == 0) answer -= 1; if(answer < 0) answer += mod; } return answer; } int main() { scanf("%d%d", &n, &q); scanf("%s", c); build_tree(); printf("%d\n", get_answer()); while(q--) { int x; scanf("%d", &x); char t; scanf(" %c", &t); update(x - 1, t); printf("%d\n", get_answer()); } return 0; } |