zoukankan      html  css  js  c++  java
  • P1169棋盘制作

    传送
    刚想提交评测姬就炸了所以我也不知道A没A
    评测姬好了我也A了
    暴力想法:对每个点(bfs),算出以这个点为左上角的最大合法矩形。复杂度(O(n^3)),但是因为数据过水可以A掉

    单调栈法

    考虑优化暴力:我们可以算出每个点在一行内最多向右扩展多长。这样计算点((i,j))为左上角的最大矩形时,从上往下扫。把每个点最多向右扩展的距离用矩形块表示,求面积时的情况:

    这样就可以用单调栈求最大矩形面积。所以最大的矩形面积就可以搞定。
    最大正方形面积:在用单调栈的时候会处理出每个矩形块能扩展出的最大矩形。用每个最大矩形中能切出的最大正方形来更新答案。
    (Code)

    #include<iostream>
    #include<cstdio>
    #include<algorithm>
    #include<cmath>
    #include<queue>
    #include<map>
    #include<cstring>
    #include<cstdlib>
    #include<set>
    #define pa pair<int,int>
    #define pi pair<ull,ll>
    using namespace std;
    const int inf=2147483640;
    typedef long long ll;
    typedef unsigned long long ull;
    inline ll read(){
    	char ch=getchar();
    	ll x=0;bool f=0;
    	while(ch<'0'||ch>'9'){
    		if(ch=='-') f=1;
    		ch=getchar();
    	}
    	while(ch>='0'&&ch<='9'){
    		x=(x<<3)+(x<<1)+(ch^48);
    		ch=getchar();
    	}
    	return f?-x:x;
    }
    const int N=2009;
    int n,m,ans1,ans2;
    int lm[N][N],pu[N],pd[N],top;//lm[i][j]表示点(i,j)最远向右扩展多少
    bool a[N][N];
    struct ST{
    	int h,pos;
    }sta[N];
    ST make(int h,int pos){
    	ST a;
    	a.h=h;a.pos=pos;
    	return a;
    }
    void orz(int x,int y){
    	top=0;int lst=n;
    	sta[++top]=make(lm[x][y],x);
    	for(int i=x;i<=n;i++){
    		if(i!=x&&a[i][y]==a[i-1][y]) {lst=i-1;break;}
    		pu[i]=i;//pu表示第i行最往上能扩展到第几行
    		if(lm[i][y]>sta[top].h){sta[++top]=make(lm[i][y],i);}
    		else { while(top&&sta[top].h>=lm[i][y]) {top--;}
    			pu[i]=sta[top].pos+1;
    			pu[i]=max(pu[i],x);//处理边界
    			sta[++top]=make(lm[i][y],i);
    		}
    	}
    	top=0;sta[++top]=make(lm[lst][y],lst);
    	for(int i=lst;i>=x;i--){
    		pd[i]=i;//pd表示向下最多扩展到第几行
    		if(lm[i][y]>sta[top].h){sta[++top]=make(lm[i][y],i);}
    		else { while(top&&sta[top].h>=lm[i][y]) {top--;}
    			pd[i]=sta[top].pos-1;
    			if(pd[i]==-1) pd[i]=lst;
    			sta[++top]=make(lm[i][y],i);
    		}
    	}
    	int S=0;
    	for(int i=x;i<=lst;i++){
            int s=(pd[i]-pu[i]+1)*lm[i][y];
            int aa=pd[i]-pu[i]+1,bb=lm[i][y];
    		ans2=max(ans2,s);
    		int l1=min(aa,bb);
    		ans1=max(ans1,l1*l1);
    	}
    }
    int main(){
    	n=read();m=read();
    	for(int i=1;i<=n;i++)
    	   for(int j=1;j<=m;j++) a[i][j]=read();
    	for(int i=1;i<=n;i++){//处理最远向右扩展
    		lm[i][m]=1;
    		for(int j=m-1;j>=1;j--){
    			if(a[i][j]!=a[i][j+1]) lm[i][j]=lm[i][j+1]+1;
    			else lm[i][j]=1;
    		}
    	}   
    	for(int i=1;i<=n;i++){
    		for(int j=1;j<=m;j++){;
    			orz(i,j);
    		}
    	}
    	printf("%d
    %d
    ",ans1,ans2);   
    }
    

    还有一种方法是悬线法但是被我咕咕咕了

  • 相关阅读:
    [Zjoi2014]力(FFT,卷积)
    LOJ 6240. 仙人掌
    Web 服务编程技巧和诀窍: 将 <xsd:any/> 元素用于自定义序列化(转)
    Ant工具使用说明(转)
    Web 服务编程技巧与窍门: 用 SAAJ 和 JAXRPC 构建 SOAP 响应信封(转)
    Axis2 quick start 中文版
    使用SOAP开发java web服务Axis开发方案(转)
    k 动画脚本很有算法 同时可以借鉴这里的画圆
    ui 界面美观化 (多维子材质脚本)
    系类函数介绍 之中可能没有一些预订变量 应用时要自己加上。
  • 原文地址:https://www.cnblogs.com/lcez56jsy/p/13897899.html
Copyright © 2011-2022 走看看