HDU 4339 Contest 4
树状数组,主要是抓住要求连续1的个数。这样,初始时,相同的加1,不同的加0.
查询时,用二分搜索右边界。就是比较当前mid-l+1的值与他们之间1的个数(这可以通过树状数组求区间和得出),记录右边界即可。
#include <iostream> #include <cstdio> #include <cstring> #include <algorithm> #include <string.h> #define lowbit(x) ((x)&(-(x))) using namespace std; const int N= 1000015; char str1[N],str2[N]; int ptree[N]; int sum(int *a,int x){ if(x==0) return 0; int s=0; for(;x;x-=lowbit(x))s+=a[x]; return s; } void update(int *a,int x,int w,int &n){ for(;x<=n;x+=lowbit(x))a[x]+=w; } int ans[100005]; int binSearch(int l,int r){ int p=l-1,tmp; int spre=sum(ptree,p); int ans=l; while(l<=r){ int mid=(l+r)/2; tmp=sum(ptree,mid); if(tmp-spre<mid-p) r=mid-1; else{ ans=mid; l=mid+1; } } return ans-p; } int main(){ int T,Q,kase=0; int ch,a,ii; char c; scanf("%d",&T); while(T--){ cin>>str1+1; cin>>str2+1; int len=min(strlen(str1+1),strlen(str2+1)); memset(ptree,0,sizeof(int)*(len+5)); for(int i=1;i<=len;i++){ if(str1[i]==str2[i]) update(ptree,i,1,len); } scanf("%d",&Q); printf("Case %d:\n",++kase); for(int i=1;i<=Q;i++){ cin>>ch; if(ch==2){ cin>>a; if(str1[a+1]!=str2[a+1]){ printf("%d\n",0); } else{ printf("%d\n",binSearch(a+1,len)); } } else{ cin>>a>>ii>>c; // cout<<a<<ii<<c<<endl; if(ii+1>len) continue; if(a==1){ if(str1[ii+1]==str2[ii+1]){ str1[ii+1]=c; if(str1[ii+1]==str2[ii+1]) continue; else update(ptree,ii+1,-1,len); } else{ str1[ii+1]=c; if(str1[ii+1]==str2[ii+1]) update(ptree,ii+1,1,len); } } else{ if(str1[ii+1]==str2[ii+1]){ str2[ii+1]=c; if(str1[ii+1]==str2[ii+1]) continue; else update(ptree,ii+1,-1,len); } else{ str2[ii+1]=c; if(str1[ii+1]==str2[ii+1]) update(ptree,ii+1,1,len); } } } } } return 0; }