题目链接:http://codeforces.com/contest/828/problem/E
题解:就是开4个数组举一个例子。
A[mod][res][i]表示到i位置膜mod余数是res的‘A’有多少个。然后以此类推其他碱基。就是单点更新区间求和用树状数组就行具体看一下代码。
#include <iostream> #include <cstring> #include <cstdio> using namespace std; const int M = 1e5 + 10; char s[M]; int T[4][11][11][M]; inline void add(int id , int mod , int res , int k , int v) { ++k; while(k < M) { T[id][mod][res][k] += v; k += (k & (-k)); } } inline int getsum(int id , int mod , int res , int k) { int ret = 0; ++k; while(k) { ret += T[id][mod][res][k]; k -= (k & (-k)); } return ret; } int main() { scanf("%s" ,s); int q , n , x , l , r; char c[20]; scanf("%d" , &q); memset(T , 0 , sizeof(T)); int L = strlen(s); for(int i = 0 ; i < L ; i++) { for(int j = 1 ; j <= 10 ; j++) { if(s[i] == 'A') add(0 , j , i % j , i , 1); if(s[i] == 'T') add(1 , j , i % j , i , 1); if(s[i] == 'G') add(2 , j , i % j , i , 1); if(s[i] == 'C') add(3 , j , i % j , i , 1); } } while(q--) { scanf("%d" , &n); if(n == 1) { scanf("%d %s" , &x , c); x--; for(int i = 1 ; i <= 10 ; i++) { if(s[x] == 'A') add(0 , i , x % i , x , -1); if(s[x] == 'T') add(1 , i , x % i , x , -1); if(s[x] == 'G') add(2 , i , x % i , x , -1); if(s[x] == 'C') add(3 , i , x % i , x , -1); } for(int i = 1 ; i <= 10 ; i++) { if(c[0] == 'A') add(0 , i , x % i , x , 1); if(c[0] == 'T') add(1 , i , x % i , x , 1); if(c[0] == 'G') add(2 , i , x % i , x , 1); if(c[0] == 'C') add(3 , i , x % i , x , 1); } s[x] = c[0]; } else { scanf("%d%d%s" , &l , &r , c); l--, r--; int len = strlen(c); int ans = 0; for(int i = 0 ; i < len ; i++) { if(c[i] == 'A') ans += (getsum(0 , len , (i + l) % len , r) - (l == 0 ? 0 : getsum(0 , len , (i + l) % len , l - 1))); if(c[i] == 'T') ans += (getsum(1 , len , (i + l) % len , r) - (l == 0 ? 0 : getsum(1 , len , (i + l) % len , l - 1))); if(c[i] == 'G') ans += (getsum(2 , len , (i + l) % len , r) - (l == 0 ? 0 : getsum(2 , len , (i + l) % len , l - 1))); if(c[i] == 'C') ans += (getsum(3 , len , (i + l) % len , r) - (l == 0 ? 0 : getsum(3 , len , (i + l) % len , l - 1))); } printf("%d " , ans); } } return 0; }