luogu1169 棋盘制作 (单调栈)

先预处理出来从每个位置 以0开始 往右交替最多能放多少格

然后就相当于对每一列做HISTOGRA

 1 #include<bits/stdc++.h>
 2 #define pa pair<int,int>
 3 #define CLR(a,x) memset(a,x,sizeof(a))
 4 using namespace std;
 5 typedef long long ll;
 6 const int maxn=2020;
 7 
 8 inline ll rd(){
 9     ll x=0;char c=getchar();int neg=1;
10     while(c<'0'||c>'9'){if(c=='-') neg=-1;c=getchar();}
11     while(c>='0'&&c<='9') x=x*10+c-'0',c=getchar();
12     return x*neg;
13 }
14 
15 int len[maxn][maxn][2];
16 int N,M,ans1,ans2;
17 bool mp[maxn][maxn];
18 int stk[maxn][2],sh;
19 
20 inline void getans(int k,bool b){
21     sh=0;
22     for(int i=1;i<=N;i++){
23         int x=len[i][k][(i&1)^b],mt=i;
24         while(sh&&x<=stk[sh][0]){
25             mt=min(mt,stk[sh][1]);
26             ans1=max(ans1,min(i-stk[sh][1],stk[sh][0]));
27             ans2=max(ans2,(i-stk[sh][1])*stk[sh][0]);
28             sh--;
29         }
30         stk[++sh][0]=x,stk[sh][1]=mt;
31     }
32 }
33 
34 int main(){
35     //freopen("","r",stdin);
36     int i,j,k;
37     N=rd(),M=rd();
38     for(i=1;i<=N;i++)
39         for(j=1;j<=M;j++)
40             mp[i][j]=rd();
41     for(i=1;i<=N;i++){
42         for(j=M;j;j--){
43             if(mp[i][j]) len[i][j][1]=len[i][j+1][0]+1;
44             else len[i][j][0]=len[i][j+1][1]+1;
45         }
46     }
47     for(i=1;i<=M;i++)
48         getans(i,0),getans(i,1);
49     printf("%d\n%d\n",ans1*ans1,ans2);
50     return 0;
51 }

 

posted @ 2018-10-22 22:23  Ressed  阅读(138)  评论(0编辑  收藏  举报