1. 程式人生 > >DNA Evolution 【CodeForces - 828E(827C)】【樹狀陣列】

DNA Evolution 【CodeForces - 828E(827C)】【樹狀陣列】

題目連結


  很難的一道題吧,算是挺難了,就是想到挺複雜,作為我這麼個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;
}