HUST 1559 ACM(树状数组)


ACM

Time Limit: 2 Sec   Memory Limit: 128 MB
Submissions: 166   Solved: 16

Description

Jianhe25 is a ACMer, he loves "ACM" very much, so he wants to know how many times "ACM" appear in the string.
Jianhe25 thinks it's so naive, so he wants to make it more difficult. He defines two types of operation:
C i x
It means to change the ith character into x , and x is a character which will always be capital letters 'A', 'C' or 'M'.
Q i j ( 1 <=i <= j<=n )
It means to count the times the substring "ACM" appear within the range of [i,j] of the string and print it on the screen.

Input

The input consists of T test cases. The number of test cases (T) is given in the first line of the input file. Each test case consists of two lines: The first line has two integers n m , 1 <= n,m <= 10000 , that represents the length of the string and the number of operations, and the second line contains n character which always be the Capital letters 'A',' C'or'M'. Followed by m lines, each line represents the operation.

Output

The output should contain the times "ACM" appear in the string, one per line.
 

Sample Input

1
6 8
ACACMM
Q 1 6
Q 1 2
C 3 M
C 4 A
C 5 C
C 6 M
Q 1 6
Q 2 4

Sample Output

1
0
2
0

HINT

Huge Input/Output , scanf/ printf is recommended.

Source

The 6th ACM Programming Contest of HUST

[ Submit][ Status][ Discuss]


题目比较简单,直接比对,结果用树状数组维护
#include <string.h>
#include <algorithm>
#include <iostream>
#include <stdio.h>
using namespace std;
const int maxn = 15000;
int n,m;
char str[maxn];
int tree[maxn];
bool rec[maxn];
int lowbit(int x){
    return x&(-x);
}
int update(int x,int num){
    while(x<=n){
        tree[x]+=num;
        x+=lowbit(x);
    }
    return 0;
}
int sum(int pos){
    int sum=0;
    while(pos>0){
        sum+=tree[pos];
        pos-=lowbit(pos);
    }
    return sum;
}
int main(){
    int i,j,k,t,a,b;
    char s[10];
    scanf("%d",&t);
    while(t--){
        scanf("%d%d",&n,&m);
        memset(tree,0,sizeof(tree));
        memset(rec,false,sizeof(rec));
        scanf("%s",str+1);
        for(i=3;i<=n;i++){
            if(str[i]=='M' && str[i-1]=='C' && str[i-2]=='A'){
                update(i,1);
                rec[i]=1;
            }
        }
        for(i=0;i<m;i++){
            scanf("%s",s);
            if(s[0]=='Q'){
                scanf("%d%d",&a,&b);
                if(a+2>b){
                    printf("0\n");
                }else{
                    printf("%d\n",sum(b)-sum(a+2)+rec[a+2]);
                }
            }else{
                scanf("%d%s",&a,s);
                if(s[0]==str[a]) continue;
                str[a]=s[0];
                if(a>=3){
                    if(rec[a]){
                        update(a,-1);
                        rec[a]=false;
                    }else{
                        if(str[a]=='M' && str[a-1]=='C' && str[a-2]=='A'){
                            update(a,1);
                            rec[a]=true;
                        }
                    }
                    if(rec[a+1]){
                        update(a+1,-1);
                        rec[a+1]=false;
                    }else{
                        if(str[a+1]=='M' && str[a-1+1]=='C' && str[a-2+1]=='A'){
                            update(a+1,1);
                            rec[a+1]=true;
                        }
                    }
                    if(rec[a+2]){
                        update(a+2,-1);
                        rec[a+2]=false;
                    }else{
                        if(str[a+2]=='M' && str[a-1+2]=='C' && str[a-2+2]=='A'){
                            update(a+2,1);
                            rec[a+2]=true;
                        }
                    }
                }
                if(a==2){
                    if(rec[a+1]){
                        update(a+1,-1);
                        rec[a+1]=false;
                    }else{
                        if(str[a+1]=='M' && str[a-1+1]=='C' && str[a-2+1]=='A'){
                            update(a+1,1);
                            rec[a+1]=true;
                        }
                    }
                    if(rec[a+2]){
                        update(a+2,-1);
                        rec[a+2]=false;
                    }else{
                        if(str[a+2]=='M' && str[a-1+2]=='C' && str[a-2+2]=='A'){
                            update(a+2,1);
                            rec[a+2]=true;
                        }
                    }
                }
                if(a==1){
                     if(rec[a+2]){
                        update(a+2,-1);
                        rec[a+2]=false;
                    }else{
                        if(str[a+2]=='M' && str[a-1+2]=='C' && str[a-2+2]=='A'){
                            update(a+2,1);
                            rec[a+2]=true;
                        }
                    }
                }
            }
        }
    }
    return 0;
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值