DNA Evolution 【CodeForces - 828E(827C)】【樹狀陣列】
阿新 • • 發佈:2018-11-20
題目連結
很難的一道題吧,算是挺難了,就是想到挺複雜,作為我這麼個Ju蒻來說。
題目給你一串字串,是初始的字串,然後告訴你一系列操作,問你:
(一)、改變點Xi上的字元;
(二)、查詢【l,r】區間上的對應與新給的字串匹配的個數是幾個?例如“ACGTCGA”我們待查的是這個完整區間上的“AG”,那麼“AG”會變成“AGAGAGA”與上述對應的點的個數就是3,第一位與最後兩位。
思路:我們發現一點,就是待查詢的區間長度很短,不超過10,那麼我們是不是可以從中挖掘出什麼來,既然最大長度為10,我們不如先做些預處理,知道原字串的樣子,我們通過其來初始化一下,就是看作每個分塊。
怎麼看作小分塊?我們從1~10的大小拆分按序全體字串,這個的目的是在於區分長度,然後,去看對應字串字元又是不同的,怎麼處理?可以再開個空間,反正就是4個字元,多開4倍還是夠的,接下來的問題就是一一對應,怎麼樣做到一一對應?我們既然已經對字串的待判長度做了預處理,不妨在想個辦法判斷出其在拆分出的字串中應當存在的位子,我們從0~len-1來排位子就是隻需要將字元所在位子去%此時的對應長度,就可以得到它應當存在的區間。
那麼樹狀陣列的開法就應當是這樣的:C[在長度為len的條件下排在第幾個][預處理長度len][元素符號][存在原陣列中的第pos位]。那麼,我們就可以建立樹狀陣列了。
細節上別忘了,每次樹狀陣列更新後記得也要改變原字串中對應位子的元素符號。
#include <iostream> #include <cstdio> #include <cmath> #include <string> #include <cstring> #include <algorithm> #include <limits> #include <vector> #include <stack> #include <queue> #include <set> #include <map> #define lowbit(x) ( x&(-x) ) #define pi 3.141592653589793 #define e 2.718281828459045 using namespace std; typedef unsigned long long ull; typedef long long ll; const int maxN = 100005; //const ull Hash1=1e9+7, Hash2=1e9+9; //const char fu[5] = { ' ', 'A' , 'T', 'G', 'C' }; const int re_fu[26] = { 1, 0, 4, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0 }; //fu[]-'A',在其中代表Z(對應符號所在的數位) char s[maxN], ques[15]; int N, Q, flag, l, r, len; int C[11][11][5][maxN]; void update(int x, int y, int z, int pos, int val) //x為數長、y為我們將其放在第幾個、z是對應的數位置,pos是我們存入的位子,val是放一個(或者刪除一個) { while(pos<maxN) { C[x][y][z][pos] += val; pos += lowbit(pos); } } int query(int x, int y, int z, int pos) //x為將其視為第幾個,y是查詢數的長度,z是待查詢的數,pos是對應字首 { int res=0; while(pos) { res += C[x][y][z][pos]; pos -= lowbit(pos); } return res; } int main() { while(scanf("%s", s+1)!=EOF) { memset(C, 0, sizeof(C)); N = (int)strlen(s+1); for(int i=1; i<=N; i++) { for(int j=1; j<=10; j++) { update(i%j, j, re_fu[s[i]-'A'], i, 1); } } scanf("%d", &Q); while(Q--) { scanf("%d", &flag); if(flag == 1) { scanf("%d", &l); scanf("%s", ques); for(int i=1; i<=10; i++) { update(l%i, i, re_fu[s[l]-'A'], l, -1); update(l%i, i, re_fu[ques[0]-'A'], l, 1); } s[l] = ques[0]; } else { int ans = 0; scanf("%d%d", &l, &r); scanf("%s", ques); len = (int)strlen(ques); for(int i=0; i<len; i++) { ans += query((l+i)%len, len, re_fu[ques[i]-'A'], r) - query( (l+i)%len, len, re_fu[ques[i]-'A'], l-1); } printf("%d\n", ans); } } } return 0; }