题目地址: http://acm.hdu.edu.cn/showproblem.php?pid=4339
12年多校 1009题。
方法: 树状数组+二分。
时间: O( n * logn * logn )
#include<cstdio>
#include<iostream>
#include<algorithm>
using namespace std;
char str[2][1001000];
int tree[1001000],mx;
void add(int v,int val){
while(v<=mx){
tree[v]+=val;
v+=v&-v;
}
}
int query(int v){
int sum=0;
while(v>=1){
sum+=tree[v];
v-=v&-v;
}
return sum;
}
int main(){
int tt,t;
int i,j,n,q,op,a,l,r,mid,now;
char c[3],ch1,ch2;
scanf("%d",&t);
for(tt=1;tt<=t;tt++){
scanf("%s",str[0]);
scanf("%s",str[1]);
scanf("%d",&q);
for(mx=0;str[0][mx]&&str[1][mx];mx++);
for(i=0;i<mx;i++)
if(str[0][i]==str[1][i]) add(i+1,1);
printf("Case %d:\n",tt);
while(q--){
scanf("%d",&op);
if(op==1){
scanf("%d%d%s",&a,&i,c);
a--;
ch1=str[a^1][i],ch2=str[a][i];
str[a][i]=c[0];
if(ch1!=ch2 && ch1==c[0]) add(i+1,1);
else if(ch1==ch2 && ch1!=c[0]) add(i+1,-1);
}
else{
scanf("%d",&i);
a=query(i+1),now=query(i);
if(a==now){
puts("0");
continue;
}
l=i+1,r=mx;
while(l<=r){
mid=(l+r)>>1;
if(query(mid)-now>=mid-i)
l=mid+1;
else r=mid-1;
}
printf("%d\n",query(r)-now);
}
}
for(i=1;i<=mx;i++) tree[i]=0;
}
return 0;
}