codeforces-827C-树状数组,同余定理

来源:互联网 发布:办公软件图标 编辑:程序博客网 时间:2024/06/14 06:35

题目大意:给定一段DNA序列,和q个query,每次可以改变一个碱基,或者查询一个区间里面有多少个碱基与给定碱基序列(可以无限重复)相同;

题目解析:首先因为匹配序列可以无限循环,所以可以根据位置%长度来确定一般性,因为如果一个碱基的位置mod (len)与匹配序列一个碱基的位置mod(len)一样,那么这个无限延长的碱基序列一定能匹配到第一个碱基,所以我们可以BIT来维护前缀和,根据碱基种类,匹配序列长度,pos%匹配序列长度来分类;

AC代码:

#include<iostream>#include<cstdio>#include<algorithm>#include<cstring>#include<string>using namespace std;const int maxn=100010;int dp[4][11][11][maxn],has[200];void init(){memset(dp,0,sizeof(dp));has['A']=0;has['T']=1;has['C']=2;has['G']=3; }int lowbit(int k){return k&(-k);}void add(int pos,int type,int val){for(int i=pos;i<maxn;i+=lowbit(i)){for(int j=1;j<=10;j++){dp[type][j][pos%j][i]+=val;}}}int query(int type,int len,int mod,int x){int ans=0;for(int i=x;i>0;i-=lowbit(i)){ans+=dp[type][len][mod][i];}return ans;}int sum(int l,int r,int mod,int type,int len){return query(type,len,mod,r)-query(type,len,mod,l-1);}char s[maxn];int main(){init();scanf("%s",&s[1]);int l=strlen(s+1);    for (int i = 1; i <=l; ++i) {          add(i, has[s[i]], 1);      }      char ch[111];      int q,a,b,c; scanf("%d", &q);      while (q--) {          scanf("%d", &a);          if (a == 1) {              scanf("%d %s", &b, ch);              add(b, has[s[b]], -1);              add(b, has[ch[0]], 1);              s[b] = ch[0];          }          else          {              scanf("%d %d %s", &b, &c, ch);              int len = strlen(ch);              int ans = 0;              for (int i = 0; i < len; ++i) {                  ans += sum(b, c, (i + b) % len, has[ch[i]], len);            }              printf("%d\n", ans);          }      }  return 0;}


原创粉丝点击