Codeforces 827C/828E DNA Evolution[树状数组]

题意:给定一个只包含A,T,C,G的字符串,有如下两种操作

1)修改一个点的字母

2)给定一个字符串e (strlen(e) <=10),生成一个由e重复组成的新串,eee...,问 L,R 区间中有几个字母跟这个新的字符串对应。


思路: 对每个字母建立10 * 10个树状数组(前面的10表示e的长度,后面表示mod e的长度后的值),表示区间中膜len(e) 结果为 k = (0...len(e)-1)的个数。

查询的话,对于给定的e 查询对应len(e)的树状数组

比如给定 e 为 ATC L = 2,R = 4

对于A 我们 查询长度为3的A的树状数组,

因为从L = 2开始,所以改为查询mod 3 == 1的总和

后面的T和C也一样。


可能说的不太清楚,,具体请见代码。

#include<bits/stdc++.h>
using namespace std;
#define _____ ios::sync_with_stdio(false); cin.tie(0);
#define ull unsigned long long
#define ll long long
#define lson l,mid,id<<1
#define rson mid+1,r,id<<1|1

typedef pair<int, int>pii;
typedef pair<ll, ll>pll;
typedef pair<double, double>pdd;

const double eps = 1e-6;
const int MAXN = 100005;
const int MAXM = 5005;
const ll LINF = 0x3f3f3f3f3f3f3f3f;
const int INF = 0x3f3f3f3f;
const double FINF = 10000000;
const ll MOD = 1000000007;
const double PI = acos(-1.0);

#define typev int                   // type of res 
typev ar[4][11][10][MAXN];                        // index: 1 ~ N 
int lowb(int t) { return t & (-t) ; } 
void add(int i,int pos,int ty,int f) {  
	for (; i < MAXN; i += lowb(i)) {
		for (int k = 1; k <= 10; ++k) {
			ar[ty][k][pos%k][i] += f;
		}
	}
}
typev sum(int i,int pos,int ty,int len) 
{  
	typev s = 0;  
	for ( ; i > 0; s += ar[ty][len][pos][i], i -= lowb(i));  
	return s; 
}
typev query(int x, int y,int pos,int ty,int len) {
	return sum(y, pos, ty, len) - sum(x - 1, pos, ty, len);
}
int Ha[100];
int main()
{
	Ha['A'] = 0, Ha['T'] = 1, Ha['G'] = 2, Ha['C'] = 3;
	string s;
	cin >> s;
	for (int i = 0; i < s.size(); ++i) {
		add(i + 1, i, Ha[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, b - 1, Ha[s[b - 1]], -1);
			add(b, b - 1, Ha[ch[0]], 1);
			s[b - 1] = 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 += query(b, c, (i + b - 1) % len, Ha[ch[i]], len);
			}
			printf("%d\n", ans);
		}
	}
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值