核苷酸(evolution)

核苷酸(evolution)

题目描述

 

生物课是帕特里克最讨厌的课程,没有之一。

相比做一些无聊而又无趣的遗传题,他更喜欢其他所有的科目。

包括英语。

但是今天不同。他被一个关于RNA感染DNA的题目所吸引了。

我希望能够实现这样的一个功能。

DNA中包含四种核苷酸,上面具有不同的含氮碱基,分别是:腺嘌呤(A)、胸腺嘧啶(T)、鸟嘌呤(G)、胞嘧啶(C)。我们可以用形如ATTGCA...的字符串来代表一条脱氧核苷酸序列。

我们需要追踪一段高变异生物的核苷酸序列。在这种生物中,其DNA序列很容易发生替换,即将某一位的核苷酸替换为其他核苷酸。

我们有一段感染串,这一条DNA单链极有可能替换原来DNA链中的核苷酸。已知这条单链会作用于[l,r][l,r]中的位置。这条单链会不重叠复制成一条长链,然后顺序感染[l,r][l,r]中的核苷酸。如果两个位置间的核苷酸不同,那么DNA链上的核苷酸就会被替换。

现在研究人员想知道,对于感染串TT,在[l,r][l,r]上有多少个位置不会受到感染。

 

输入

 

 

第一行一串字符串,初始DNA链SS。SS仅由A,T,G,C四个大写字母组成。

接下来一行带有一个整数QQ。接下来QQ行每行一个询问,格式如下:

1 x C,表示第xx位置上的核苷酸被替换成字符CC。

2 l r T,表示有可能有一个感染串TT,在[l,r][l,r]间作用。

注意,每次感染串并不会对原串做出任何修改。

 

 

 

输出

 

对于每个查询22,输出不会受感染的核苷酸位置数量。

 

样例输入

【样例1输入】
ATGCATGC
4
2 1 8 ATGC
2 2 6 TTT
1 4 T
2 2 6 TA
【样例2输入】
GAGTTGTTAA
6
2 3 4 TATGGTG
1 1 T
1 6 G
2 5 9 AGTAATA
1 10 G
2 2 6 TTGT

样例输出

【样例1输出】
8
2
4
【样例2输出】
0
3
1

提示

 

你可以将感染串理解成一个循环节为|T||T|的无限长字符串。

请结合两个样例理解其意义。

 

对于30%的数据,1≤|S|,Q≤1031≤|S|,Q≤103。

对于另外10%的数据,没有修改操作。

对于另外10%的数据,基因串仅由A,T两字符构成。

对于所有数据,满足:1≤|S|,Q≤105,1≤|T|≤101≤|S|,Q≤105,1≤|T|≤10,询问中x,l,r≤|S|x,l,r≤|S|。所有字符与字符串均只包含A,T,G,C。

另,最伟大的创造是光合作用。

 

 

来源

lhy

 

solution

令a[p][m][r][x]表示S串中前x个位置

有多少个字母p (ATGC)的位置

模m

余r

对于每一位s[x]

a[s[x]][mod][i%mod][x]++;

前缀和维护即可

 

#include<cstdio>
#include<iostream>
#include<cstdlib>
#include<cstring>
#include<algorithm>
#include<cmath>
using namespace std;
int n,Q,m,a[4][11][11][100005],op,pl,l,r;
char s[100005],ch[15],dy[200],tt;
void jia(int c,int p,int r,int x,int v){
	for(;x<=n;x+=(x&-x))a[c][p][r][x]+=v;
}
int cha(int c,int p,int r,int x){
	int vv=0;
	for(;x>0;x-=(x&-x))vv+=a[c][p][r][x];
	return vv;
}
int main()
{
	dy['A']=0;dy['T']=1;dy['G']=2;dy['C']=3;
	scanf("%s",s+1);
	n=strlen(s+1);
	for(int i=1;i<=n;i++){
		for(int mod=1;mod<=10;mod++){
			jia(dy[s[i]],mod,i%mod,i,1);
		}
	}
	cin>>Q;
	while(Q--){
		scanf("%d",&op);
		if(op==1){
			scanf("%d %c",&pl,&tt);
			for(int mod=1;mod<=10;mod++){
				jia(dy[s[pl]],mod,pl%mod,pl,-1);
				jia(dy[tt],mod,pl%mod,pl,1);
			}
			s[pl]=tt;
		}
		else {
			scanf("%d%d%s",&l,&r,ch);
			m=strlen(ch);
			int sum=0;
			for(int i=0;i<m;i++){
				int s1=cha(dy[ch[i]],m,(i+l)%m,l-1);
				int s2=cha(dy[ch[i]],m,(i+l)%m,r);
				sum+=s2-s1;
			}
			printf("%d\n",sum);
		}
	}
	return 0;
}

猜你喜欢

转载自blog.csdn.net/liankewei123456/article/details/81668139