hdu 4339 Query 一道挺好的树状数组题(树状数组+二分思想)

题意:首先给了两个字符串,然后有两种类型的操作,第一种:1 a i c 你应该把第i个字符串的第a个字符变成c;第二种:2 i 就是问你从第i个字符开始两个字符串连续的最长的相等长度。

 

思路:利用树状数组更新和求和,对于第二种操作就是利用二分求得的连续最长的长度。

代码实现:

#include<iostream>
#include<cstring>
using namespace std;
char str1[1000001],str2[1000001];
int a[1000001],len1,len2;
int lowbit(int x)
{
    return x&(-x);
}
void build(int x,int num)//构造树状数组
{
   while(x<=len1)
   {
       a[x]=a[x]+num;
       x=x+lowbit(x);
   }
}
int sum(int x)//求和
{
    int s=0;
    while(x>=1)
    {
        s=s+a[x];
        x=x-lowbit(x);
    }
    return s;
}
int main()
{
    int T,nima,i,Q,x1,x2,x3,nima1,nima2;
    char temp;
    while(scanf("%d",&T)!=EOF)
    {
        getchar();
        nima=0;
        while(T--)
        {
          nima++;
          scanf("%s%s",str1+1,str2+1);//数组下标从1开始
          printf("Case %d:\n",nima);
          len1=strlen(str1+1);
          len2=strlen(str2+1);
          len1=len1>len2?len2:len1;//去两者中短的
          for(i=0;i<=len1;i++)
              a[i]=0;//树状数组的初始化
          for(i=1;i<=len1;i++)
              if(str1[i]==str2[i])
                 build(i,1);
          scanf("%d",&Q);
          while(Q--)
          {
              scanf("%d",&x1);
              if(x1==1)
              {
                  scanf("%d%d %c",&x2,&x3,&temp);
                  getchar();
                  if(x3+1<=len1)
                  {
                      if(x2==1)//对第一个字符串进行操作
                      {
                         if(str1[x3+1]==str2[x3+1]&&str2[x3+1]!=temp)
                            build(x3+1,-1);
                         else if(str1[x3+1]!=str2[x3+1]&&str2[x3+1]==temp)
                             build(x3+1,1);
                         str1[x3+1]=temp;
                      }
                      else
                      {
                          if(str1[x3+1]==str2[x3+1]&&str1[x3+1]!=temp)
                            build(x3+1,-1);
                          else if(str1[x3+1]!=str2[x3+1]&&str1[x3+1]==temp)
                            build(x3+1,1);
                          str2[x3+1]=temp;
                      }
                  }
              }
              else
              {
                  scanf("%d",&x2);
                  if(x2>len1)
                      printf("%d\n",0);
                  else
                  {
                      nima1=x2+1;nima2=len1;
                      while(nima1<=nima2)//二分思想
                      {
                         int mid=(nima1+nima2)/2;
                         if((sum(mid)-sum(nima1-1))==(mid-nima1+1))//左边连续
                             nima1=mid+1;
                         else//左边不连续
                             nima2=mid-1;
                      }
                      printf("%d\n",nima2-x2);
                  }
              }
          }
        }
    }
    return 0;
}

 

转载于:https://www.cnblogs.com/jiangjing/archive/2013/01/19/2868113.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值