codeforce828E. DNA Evolution【樹狀陣列統計貢獻】
阿新 • • 發佈:2018-11-24
文章目錄
題目連結:
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;
}
}
}
}