• ●CodeForces 480E Parking Lot


    题链:

    http://codeforces.com/problemset/problem/480/E
    题解:

    单调队列,逆向思维
    (在线的话应该是分治做,但是好麻烦。。)
    离线操作,逆向考虑,
    最后的状态可以用O(N*M)的dp得出最大正方形边长。
    然后反向一个一个的把障碍变回非障碍,显然答案不会变小。
    维护好up[i][j],down[i][j],分别表示从(i,j)位置向上向下有多长的连续非障碍。
    不难发现,如果有更大的答案的话,那么必然包含当前改变的位置的那一行的某些格子。
    所以确定了在这一行上寻找是否有更大的答案,
    然后就用单调队列维护来求出当前行上的最大正方形即可。


    代码:

    #include<bits/stdc++.h>
    #define MAXN 2005
    using namespace std;
    struct CMD{int x,y,ans;}C[MAXN];
    bool graph[MAXN][MAXN];
    int up[MAXN][MAXN],down[MAXN][MAXN];
    int N,M,K,ANS;
    void update(int j){
    	for(int i=1;i<=N;i++)
    		up[i][j]=graph[i][j]?up[i-1][j]+1:0;
    	for(int i=N;i>=1;i--)
    		down[i][j]=graph[i][j]?down[i+1][j]+1:0;
    }
    void prework(){
    	static int dp[MAXN][MAXN];
    	for(int i=1;i<=N;i++)
    		for(int j=1;j<=M;j++){
    			if(graph[i][j]==0) dp[i][j]=0;
    			else dp[i][j]=min(dp[i-1][j-1],min(dp[i-1][j],dp[i][j-1]))+1;
    			ANS=max(ANS,dp[i][j]);
    		}
    	for(int j=1;j<=M;j++) update(j);
    }
    int main(){
    	char ch;
    	scanf("%d%d%d",&N,&M,&K);
    	for(int i=1;i<=N;i++)
    		for(int j=1;j<=M;j++)
    			scanf(" %c",&ch),graph[i][j]=ch=='.'?1:0;
    	for(int i=1;i<=K;i++)
    		scanf("%d%d",&C[i].x,&C[i].y),graph[C[i].x][C[i].y]=0;
    	prework(); C[K].ans=ANS;
    	static int ql[MAXN],qr[MAXN],qll,qlr,qrl,qrr;
    	for(int i=K,ret,x,l,r,h;i>=1;i--){
    		ret=0; x=C[i].x;
    		graph[C[i].x][C[i].y]=1;
    		update(C[i].y);
    		qll=qrl=l=1; qlr=qrr=r=0;
    		while(l<=M){
    			h=-233;
    			if(l<=r){
    				h=up[x][ql[qll]]+down[x][qr[qrl]]-1;
    				ret=max(ret,min(h,r-l+1));
    			}
    			if(r<M&&(h==-233||h>=r-l+1)){
    				r++;
    				while(qll<=qlr&&up[x][ql[qlr]]>=up[x][r]) qlr--; ql[++qlr]=r;
    				while(qrl<=qrr&&down[x][qr[qrr]]>=down[x][r]) qrr--;qr[++qrr]=r;
    			}
    			else{
    				l++;
    				while(qll<=qlr&&ql[qll]<l) qll++;
    				while(qrl<=qrr&&qr[qrl]<l) qrl++;
    			}
    		}
    		ANS=max(ret,ANS);
    		C[i-1].ans=ANS;
    	}
    	for(int i=1;i<=K;i++) printf("%d
    ",C[i].ans);	
    	return 0;
    }
    

      

  • 相关阅读:
    连锁超市价格表 超市商品价格目录表
    无线路由器后台破解无需密码登录, 什么是网桥,怎么设置网桥
    做技术安卓开发程序员怎么赚钱
    QQ怎么 发送 已经录好的视频
    win 10 文件夹 背景 没效果
    夏婉安
    Navicat Premium 激活码 序列号。破解版。
    韩梦飞沙Android应用集合 想法
    安卓 开机 动画 酷派大神F1开机动画 美化 自定义 修改
    android 视频 2017
  • 原文地址:https://www.cnblogs.com/zj75211/p/8541900.html
Copyright © 2020-2023  润新知