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:
",++kase);
		for(int i=1;i<=Q;i++){
			cin>>ch;
			if(ch==2){
				cin>>a;
				if(str1[a+1]!=str2[a+1]){
					printf("%d
",0);
				}
				else{
					printf("%d
",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;
}

  

原文地址:https://www.cnblogs.com/jie-dcai/p/4119265.html