Codeforces 827C DNA Evolution(多维树状数组)

来源:互联网 发布:linux显示文本名 编辑:程序博客网 时间:2024/05/29 17:34

题意:

给定一个只包含A,T,C,G的字符串,有如下两种操作
1)修改一个点的字母
2)给定区间L, R和一个字符串e (strlen(e) <=10),组成一个足够区间长度的由若干个e重复组成的新串,eee...,问L,R区间中有几个位置对应的字母跟这个新的字符串对应的相同。

思路:

因为e的长度最多才10,所以对于一个字母,它最多有10个不同的起始位置,10个不同的长度进行重复,所以建立一个4*10*10的树状数组,再维护就可以了。
注意维护和查询时候的细节就好了,并不难。

代码:

#include <bits/stdc++.h>using namespace std;const int maxn = 1e5+5;char s[maxn], e[11];map<char, int> mp;int c[11][11][4][maxn], cnt[11][11];int n, len;int lowbit(int x) {return x & -x;}void update(int x, int y, int z, int pos, int val){while(pos <= cnt[x][y]){c[x][y][z][pos] += val;pos += lowbit(pos);}}int query(int x, int y, int z, int pos){int ans = 0;while(pos){ans += c[x][y][z][pos];pos -= lowbit(pos);}return ans;}void init(){memset(c, 0, sizeof c);mp['A'] = 0, mp['T'] = 1, mp['G'] = 2, mp['C'] = 3;len = strlen(s+1);for(int i = 1; i <= min(10, len); ++i)for(int j = i; j <= 10; ++j){cnt[i][j] = (len-i)/j+1;for(int k = 0; i+k*j <= len; ++k){if(s[i+k*j] == 'A') update(i, j, 0, k+1, 1);if(s[i+k*j] == 'T') update(i, j, 1, k+1, 1);if(s[i+k*j] == 'G') update(i, j, 2, k+1, 1);if(s[i+k*j] == 'C') update(i, j, 3, k+1, 1);}}}void change(int t, char e){    int mmp = min(min(10, len), t);for(int i = 1; i <= mmp; ++i)for(int j = i; j <= 10; ++j){    if((t-i)%j == 0)        {            int k = (t-i)/j;            update(i, j, mp[s[t]], k+1, -1);update(i, j, mp[e], k+1, 1);        }}s[t] = e;}int main(){ios::sync_with_stdio(0);cin >> s+1;init();cin >> n;int key, x, l, r;for(int i = 1; i <= n; ++i){cin >> key;if(key == 1){cin >> x;cin >> e;change(x, e[0]);}if(key == 2){cin >> l >> r;cin >> e+1;int ans = 0, elen = strlen(e+1);for(int j = 1; l+j-1 <= r && j <= elen; ++j){int start = (l+j-1)%elen;if(start == 0) start = elen;if(l-1-start >= 0){int ll = (l-1-start)/elen+1;ans -= query(start, elen, mp[e[j]], ll);}if(r-start >= 0){int rr = (r-start)/elen+1;ans += query(start, elen, mp[e[j]], rr);}}cout << ans << endl;}}return 0;}


继续加油~