树状数组好题(codeforces828E)

来源:互联网 发布:淘宝店铺运营费用 编辑:程序博客网 时间:2024/06/02 00:25

题意:给你一个只包含四字母的字符串,用另一个字符串去匹配该字符串的一个区间,第二个字符串只是一个循环节,知道把区间全部匹配一次,计算相同的字母数。经典的单点更新和区间求和的问题(有没有感觉?)

题解:因为只包含四种字母,第一感觉就想分块搞。但是又和前缀和没什么关系,因为得比较每一位。但是第二个字符串又只有10,相当于什么呢?把整个数列分成10块的,更新的时候就只需要看属于那一块,然后往后更新答案就好了。求和的时候呢?只需要看这个字符串的每一位位于哪一个10的块里面。然后求这个区间内这一位有多少相同的,就OK了。下面是具体代码、

#include<bits/stdc++.h>using namespace std;typedef long long ll;const int INF=0x3f3f3f3f;char str[100010];struct BIT{    int d[100010];    void add(int x,int y)    {        while(x<=100001)        {            d[x]+=y;            x+=x&-x;        }    }    int sum(int x)    {        int ans=0;        while(x)        {            ans+=d[x];            x-=x&-x;        }        return ans;    }    int get(int l,int r)    {        return sum(r)-sum(l-1);    }}t[12][12][5];int mapp[100];int main(){    int q;    mapp['A']=0;mapp['T']=1;mapp['C']=2;mapp['G']=3;    scanf("%s",str+1);    int len=strlen(str+1);    for(int i=1;i<=10;i++)        for(int j=1;j<=len;j++)            t[i][j%i][mapp[str[j]]].add(j,1);    scanf("%d",&q);    while(q--)    {        int op;        scanf("%d",&op);        char s2[15];        if(op==1)        {            int x;            scanf("%d%s",&x,s2);            for(int i=1;i<=10;i++)            {                t[i][x%i][mapp[str[x]]].add(x,-1);                t[i][x%i][mapp[s2[0]]].add(x,1);            }            str[x]=s2[0];        }        else        {            int ans=0;            int l,r;            scanf("%d%d%s",&l,&r,s2);            int l2=strlen(s2);            for(int i=0;i<l2;i++)                ans+=t[l2][(l+i)%l2][mapp[s2[i]]].get(l,r);            printf("%d\n",ans);        }    }    return 0;}


原创粉丝点击