• HDU—4046 Panda (线段树)


    题目:http://acm.hdu.edu.cn/showproblem.php?pid=4046

    题意:给出一个字符串,统计这个字符串任意区间中“wbw”出现的次数。

    规定两种操作,一是查询任意区间“wbw”出现次数;二是修改某一位置的字符。

    分析:比较明显的线段树,单点更新,区间查询。

    线段树记录的信息是区间中出现“wbw”字符的个数,线段树的叶子节点[i,i]记录字符串str中

    str[i-2][i-1][i]是否是“wbw“。

    对于字符的修改,这里就有要注意了。修改的位置pos, 可能对线段树中sum[pos-1]   sum[pos] 或sum[pos+1]

    造成影响。这里要分情况。

    代码

    #include<cstdio>
    
    #include<cstring>
    
    #define lson l,m,rt<<1
    
    #define rson m+1,r,rt<<1|1
    
    using namespace std;
    
    const int maxn=50010;
    
    int n,m,sum[maxn<<2];
    
    char str[maxn];
    
    int num[maxn];
    
    void pushup(int rt)
    
    {
    
    	sum[rt]=sum[rt<<1]+sum[rt<<1|1];
    
    }
    
    void build(int l,int r,int rt)
    
    {
    
    	if(l==r)
    
    	{
    
    		sum[rt]=num[l];
    
    		return;
    
    	}
    
    	int m=(l+r)>>1;
    
    	build(lson);
    
    	build(rson);
    
    	pushup(rt);
    
    }
    
    int query(int L,int R,int l,int r,int rt)
    
    {
    
    	if(L<=l&&r<=R)
    
    	{
    
    		return sum[rt];
    
    	}
    
    	int m=(l+r)>>1;
    
    	int ans=0;
    
    	if(L<=m) ans+=query(L,R,lson);
    
    	if(R>m)  ans+=query(L,R,rson);
    
    	return ans;
    
    }
    
    void update(int p,int val,int l,int r,int rt)
    
    {
    
    	if(l==r)
    
    	{
    
    		sum[rt]=val;
    
    		return;
    
    	}
    
    	int m=(l+r)>>1;
    
    	if(p<=m) update(p,val,lson);
    
    	else 	 update(p,val,rson);
    
    	pushup(rt);
    
    }
    
    int main()
    
    {
    
    	int t,T;
    
    	scanf("%d",&T);
    
    	for(int t=1;t<=T;t++)
    
    	{
    
    		printf("Case %d:
    ",t);
    
    		scanf("%d%d%s",&n,&m,str+1);
    
    		memset(num,0,sizeof(num));
    
    		for(int i=3;i<=n;i++)
    
    			if(str[i-2]=='w'&&str[i-1]=='b'&&str[i]=='w')  num[i]=1;
    
    		build(1,n,1);
    
    		int k,a,b;
    
    		char ch[5];
    
    		while (m--)
    
    		{
    
    			scanf("%d",&k);
    
    			if(k==0)
    
    			{
    
    				scanf("%d%d",&a,&b);
    
    				a++;b++;   //字符串从1开始,所以下标都加1
    
    				if(b-a<2)  printf("0
    ");
    
    				else       printf("%d
    ",query(a+2,b,1,n,1));
    
    			}
    
    			else
    
    			{
    
    				scanf("%d%s",&a,ch);
    
    				a++;
    
    				if(ch[0]==str[a]) continue;//修改的和以前一样,这不用任何操作
    
    				if(a>=3)
    
    				{
    
    					if(str[a-2]=='w'&&str[a-1]=='b'&&str[a]=='w')
    
    						update(a,0,1,n,1);
    
    					if(str[a-2]=='w'&&str[a-1]=='b'&&str[a]=='b')
    
    						update(a,1,1,n,1);
    
    				}
    
    				if(a>=2&&a+1<=n)
    
    				{
    
    					if(str[a-1]=='w'&&str[a]=='b'&&str[a+1]=='w')
    
    						update(a+1,0,1,n,1);
    
    					if(str[a-1]=='w'&&str[a]=='w'&&str[a+1]=='w')
    
    						update(a+1,1,1,n,1);
    
    				}
    
    				if(a+2<=n)
    
    				{
    
    					if(str[a]=='w'&&str[a+1]=='b'&&str[a+2]=='w')
    
    						update(a+2,0,1,n,1);
    
    					if(str[a]=='b'&&str[a+1]=='b'&&str[a+2]=='w')
    
    						update(a+2,1,1,n,1);
    
    				}
    
    				str[a]=ch[0];
    
    			}
    
    		}
    
    	}
    
    	return 0;
    
    }
    

  • 相关阅读:
    C# 序列化技术详解《转》
    DataGridView中的DataGridViewComboBoxColumn使用浅析
    取EXCEL文件的3种方法
    教你几种在SQLServer中删除重复数据方法
    事件浅析
    迭代委托链
    C#调用耗时函数时显示进度条浅探
    启动公告【过时】
    在Web应用中接入微信支付的流程之极简清晰版
    VBoxManage: error: Cannot register the hard disk 解决办法
  • 原文地址:https://www.cnblogs.com/gt123/p/3705621.html
Copyright © 2020-2023  润新知