您的位置:首页 > 产品设计 > UI/UE

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

2013-01-19 22:29 309 查看
题意:首先给了两个字符串,然后有两种类型的操作,第一种: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;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: