HDU4046panda (线段树)

题意:

给出一个只包含w和b的字符串,要求支持一下两种操作:1,统计区间[a,b]中wbw的数量。2,修改a[p]的值为v。

分析:

线段树,sum[o]为结点o的wbw的数量。

在建树时,对与o结点的sum[o]=sum[2*o]+sum[2*o+1];如果两个结点连接处有wbw则将sum[o]++;更新的过程类似于建树的过程。

在查询[ql,qr]区间的wbw数量时,当两个区间合并时若连接处有wbw则_sum++;注意这里和建树和更新时候的区别。

#include <cstdio>
#include <algorithm>
#include <iostream>
#include <cstring>
using namespace std;
const int maxn=50000+100;
int n,m,T;
int num[4*maxn];
char s[maxn];
void build(int o,int L,int R){
    int M=L+(R-L)/2;
    if(L==R){
        num[o]=0;
        return ;
    }
    build(2*o,L,M);
    build(2*o+1,M+1,R);
    num[o]=num[2*o]+num[2*o+1];
    if(R-L>1){
        if(s[M]=='b'&&s[M-1]=='w'&&s[M+1]=='w'&&M-L>=1)
            num[o]++;
        if(s[M]=='w'&&s[M+2]=='w'&&s[M+1]=='b'&&R-M>=2)
            num[o]++;
    }
}
int p;//A[p]=v
char v;
void update(int o,int L,int R){
    int M=L+(R-L)/2;
    if(L==R){
        s[L]=v;
        num[o]=0;
        return ;
    }
    if(p<=M)update(2*o,L,M);
    if(p>M)update(2*o+1,M+1,R);
    num[o]=num[2*o]+num[2*o+1];
    if(R-L>1){
        if(s[M]=='b'&&s[M-1]=='w'&&s[M+1]=='w'&&M-L>=1)
            num[o]++;
        if(s[M]=='w'&&s[M+2]=='w'&&s[M+1]=='b'&&R-M>=2)
            num[o]++;
    }
}
int ql,qr,_sum;
void query(int o,int L,int R){
    if(ql<=L&&qr>=R){
        _sum+=num[o];
        return;
    }
    int M=L+(R-L)/2;
    if(ql<=M)query(2*o,L,M);
    if(qr>M)query(2*o+1,M+1,R);
    if(ql<=M&&qr>M){
        if(R-L>1){
            if(s[M]=='b'&&s[M-1]=='w'&&s[M+1]=='w'&&M-ql>=1&&M-L>=1)//注意这里
                _sum++;
            if(s[M]=='w'&&s[M+2]=='w'&&s[M+1]=='b'&&qr-M>=2&&R-M>=2)
                _sum++;
        }
    }
}
void tra(int o,int L,int R){
    cout<<L<<"->"<<R<<" "<<num[o]<<endl;
    if(L==R)
        return ;
    int M=L+(R-L)/2;
    tra(2*o,L,M);
    tra(2*o+1,M+1,R);
}
int main(){
    scanf("%d",&T);
    for(int k=1;k<=T;k++){
        cout<<"Case "<<k<<":"<<endl;
        scanf("%d%d",&n,&m);
        scanf("%s",s);
        build(1,0,n-1);
        //tra(1,0,n-1);
        int c;
        for(int i=1;i<=m;i++){
            scanf("%d",&c);
            if(c==0){
                scanf("%d%d",&ql,&qr);
                _sum=0;
                query(1,0,n-1);
                cout<<_sum<<endl;
            }
            if(c==1){
                scanf("%d %c",&p,&v);
                update(1,0,n-1);
                //tra(1,0,n-1);
            }
        }
    }
return 0;
}


--------------------------------------------------------------------------------------我是分割线--------------------------------------------------------------------------------------------------------------------------------

刚刚去看了看大佬们的写法,发现自己写的太渣了。

对于wbw,只需统计符合wbw形式的b的数量就可以,先进行预处理,若s[i]=b,s[i-1]=s[i+1]=w;则a[i]=1,否则a[i]=0;那么对于查询[ql,qr]时,只需知道区间[ql,qr]内a[i]的区间和即可。只要这样预处理,题目便变成了最基本的点修改线段树


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值