1. 程式人生 > >codeforce828E. DNA Evolution【樹狀陣列統計貢獻】

codeforce828E. DNA Evolution【樹狀陣列統計貢獻】

文章目錄

題目連結:

http://codeforces.com/problemset/problem/828/E
題意:先給一個DNA序列,然後有兩種操作
操作1:把 x 位置的鹼基改成 c
操作2:給一個 L 和一個 R ,以及一個字串 s ,這個字串s是一直迴圈重複的,比如s=‘ATC’,那就是’ATCATCATCATC…'一直迴圈下去。問在[L,R]中,對應位置字元相同的有多少個?

看了題解之後,我才反應過來,DNA序列與所給的這個字串是從頭開始對齊然後來比對的,而不需要找對應位置相同最多而去移動他,因此所有資訊已給出,兩個串的相對位置就是固定的了,而這道題的關鍵就是所給的字串 s 的長度非常小,不然就不好做了

哇~所以才有的長這種樣子的樹狀陣列,就是DNA中第 i 個的這種字元,與長度為 s 的字串延長後的第 i 個這種字元相同的數量,因為4種鹼基都要統計,所以要4個樹狀陣列來統計

每種鹼基的樹狀陣列來統計當把DNA分成len段len段的時候的這種鹼基在x%len位置上的個數

這道題是個讓我闊以回味的題~good題

#include"bits/stdc++.h"
using namespace std;
typedef long long LL;
const int maxn=1e5+5;
const int MOD=1e9+7;
char DNA[maxn];
struct BitTree
{
int tree[maxn]; void add(int pos,int v) { for(int i=pos; i<maxn; i+=i&-i)tree[i]+=v; } int getsum(int pos) { int res=0; for(int i=pos; i>=1; i-=i&-i)res+=tree[i]; return res; } int query(int L,int R) { return getsum(R)-getsum(L-1); } }; BitTree a[11][11][4]; int main
() { map<char,int>Mp; Mp['A']=0; Mp['G']=1; Mp['C']=2; Mp['T']=3; while(cin>>(DNA+1)) { memset(a,0,sizeof a); int N=strlen(DNA+1); /*預處理出所有資訊存到樹狀陣列中*/ //把DNA分成len段len段的,儲存對應位置是某個鹼基的個數 for(int len=1; len<=10; len++) { for(int i=1; i<=N; i++) { a[len][i%len][Mp[DNA[i]]].add(i,1); } } int Q; cin>>Q; while(Q--) { int cmd; scanf("%d",&cmd); char s[15]; if(cmd==1) { int x; scanf("%d%s",&x,s); for(int len=1; len<=10; len++) { a[len][x%len][Mp[DNA[x]]].add(x,-1);//手賤x寫成i了,以後都改成while(Q--)好了,不用for迴圈了 a[len][x%len][Mp[s[0]]].add(x,1); } DNA[x]=s[0];//這個忘了改了就WA了 } else { int L,R; scanf("%d%d%s",&L,&R,s); int len=strlen(s); int res=0; for(int i=0;i<len;i++) { res+=a[len][(i+L)%len][Mp[s[i]]].query(L,R);//根據預處理出來的資訊來查詢有多少個 } cout<<res<<endl; } } } }