「晚间测试8」physics

题意:

最大正方形+修改操作,每个修改后查询最大正方形

解法:

当然是随机化乱搞啊(假装不是修改)

没修改,是wmz的视察(最大正方形),\(O(n^2)\)DP乱搞

带修改后,发现正着做十分费劲,考虑倒着做,即先把所有修改离线,并直接修改,然后从后往前还原,类似的思想在修改并查集里有所体现

记录每个点在当前列向上和向下分别能扩展的最远点,以上一次修改的点为中心,二分正方形长度,因为对于一个0变1的点,可能产生的新最大正方形一定包括修改点

二分的\(check\)函数,可以写一个单调队列,维护上下边界的最值,判断上下最值和滑动窗口长度是否不小于二分长度

没了

时间复杂度:\(O(n^2log)\)

\(O(n^2)\)的做法,懒得写了,康康其他人的博客就行

bool check(int len,int x){
	int head1=1,tail1=0,head2=1,tail2=0,last=0;
	memset(q1,0,sizeof(q1));
	memset(q2,0,sizeof(q2));
	for(int j=1;j<=m;j++){
		while(head1<=tail1&&up[x][j]>up[x][q1[tail1]])tail1--;
		while(head1<=tail1&&j-q1[head1]+1>len)head1++;
		if(a[x][j])q1[++tail1]=j;
		else head1=j+1,tail1=j;
		while(head2<=tail2&&down[x][j]<down[x][q2[tail2]])tail2--;
		while(head2<=tail2&&j-q2[head2]+1>len)head2++;
		if(a[x][j])q2[++tail2]=j;
		else head2=j+1,tail2=j,last=j+1;
		if(j-last+1>=len&&down[x][j-len+1]-up[x][j-len+1]+1>=len&&down[x][q2[head2]]-up[x][q1[head1]]+1>=len){return 1;}
	}
	return 0;
}
#define mid ((l+r)>>1)
int Binary(int l,int r,int x){
	while(l<=r){
		//if(x==5)cout<<mid<<" "<<check(mid,x)<<" "<<l<<" "<<r<<" "<<endl;
		if(check(mid,x))l=mid+1;
		else r=mid-1;
	}
	return l-1;
}
int main(){
	freopen("physics.in","r",stdin);
	freopen("physics.out","w",stdout);
	n=read(),m=read(),q=read();
	for(register int i=1;i<=n;++i)scanf("%s ",b[i]+1);
	for(register int i=1;i<=n;++i){
		for(register int j=1;j<=m;j++){
			if(b[i][j]=='+')a[i][j]=1;
		}
	}
	for(int i=1;i<=q;i++){
		qx[i]=read();qy[i]=read();a[qx[i]][qy[i]]=0;
	}
	for(int i=1;i<=n;i++){
		for(int j=1;j<=m;j++){
			if(!a[i][j])f[i][j]=0;
			else f[i][j]=min(f[i-1][j-1],min(f[i-1][j],f[i][j-1]))+a[i][j];
			ans[q]=max(ans[q],f[i][j]);
		}
	}
	a[qx[q]][qy[q]]=1;
	for(int j=1;j<=m;j++){
		for(int i=1;i<=n;i++){
			if(!a[i-1][j]&&a[i][j])up[i][j]=i;
			else if(a[i][j])up[i][j]=up[i-1][j];
		}
	}
	for(int j=m;j>=1;j--){
		for(int i=n;i>=1;i--){
			if(!a[i+1][j]&&a[i][j])down[i][j]=i;
			else if(a[i][j])down[i][j]=down[i+1][j];
		}
	}
	for(int i=q-1,x,y,last=qx[q];i>=1;i--){
		x=qx[i],y=qy[i];
		ans[i]=max(Binary(1,n,last),ans[i+1]);
		a[x][y]=1;//cout<<i<<endl;
		for(int j=1;j<=n;j++){
			if(!a[j-1][y]&&a[j][y])up[j][y]=j;
			else if(a[j][y])up[j][y]=up[j-1][y];
			else if(!a[j][y])up[j][y]=0;
		}
		for(int j=n;j>=1;j--){
			if(!a[j+1][y]&&a[j][y])down[j][y]=j;
			else if(a[j][y])down[j][y]=down[j+1][y];
			else if(!a[j][y])down[j][y]=0;
		}
		last=x;
	}
	for(int i=1;i<=q;i++)printf("%d\n",ans[i]);
	return 0;
}

posted @ 2020-10-17 20:12  _乀aakennes  阅读(117)  评论(0编辑  收藏  举报
levels of contents