• 「晚间测试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
    ",ans[i]);
    	return 0;
    }
    
    
  • 相关阅读:
    bash task list and interrupt
    bash字符串大小写转换方法
    Spectrum Mask
    OFDM中CP的优缺点
    模块边界使用寄存器来做数据的交互
    跨时钟域信号处理
    FPGA中一个Slice所含资源
    Verilog中if-else改写成case的方法
    同步序列的自相关与互相关
    TCP三次握手四次挥手
  • 原文地址:https://www.cnblogs.com/614685877--aakennes/p/13832379.html
Copyright © 2020-2023  润新知