棋盘制作
SOL
悬线法板题
设
l
[
i
]
[
j
]
l[i][j]
l[i][j]表示
(
i
,
j
)
(i,j)
(i,j)可以到达的最左端
r
[
i
]
[
j
]
r[i][j]
r[i][j]表示
(
i
,
j
)
(i,j)
(i,j)可以到达的最右端
u
p
[
i
]
[
j
]
up[i][j]
up[i][j]表示
(
i
,
j
)
(i,j)
(i,j)可以到达的最上端
l
l
l,
r
r
r可以先预处理出来
更新答案时,若
a
[
i
]
[
j
]
!
=
a
[
i
−
1
]
[
j
]
a[i][j]!=a[i-1][j]
a[i][j]!=a[i−1][j]
就可以进行如下操作:
l
[
i
]
[
j
]
=
m
a
x
(
l
[
i
]
[
j
]
,
l
[
i
−
1
]
[
j
]
)
,
r
[
i
]
[
j
]
=
m
i
n
(
r
[
i
]
[
j
]
,
r
[
i
−
1
]
[
j
]
)
,
u
p
[
i
]
[
j
]
=
u
p
[
i
−
1
]
[
j
]
+
1
l[i][j]=max(l[i][j],l[i-1][j]),r[i][j]=min(r[i][j],r[i-1][j]),up[i][j]=up[i-1][j]+1
l[i][j]=max(l[i][j],l[i−1][j]),r[i][j]=min(r[i][j],r[i−1][j]),up[i][j]=up[i−1][j]+1
之后直接更新答案即可
代码:
#include<bits/stdc++.h>
using namespace std;
#define re register
inline int rd(){
int re data=0;static char ch=0;ch=getchar();
while(!isdigit(ch))ch=getchar();
while(isdigit(ch))data=(data<<1)+(data<<3)+(ch^48),ch=getchar();
return data;
}
const int N=2005;
int n,m,l[N][N],r[N][N],up[N][N],mx1,mx2;bool a[N][N];
signed main(){
n=rd(),m=rd();
for(int re i=1;i<=n;++i)for(int re j=1;j<=m;++j)a[i][j]=rd(),l[i][j]=r[i][j]=j,up[i][j]=1;
for(int re i=1;i<=n;++i)for(int re j=2;j<=m;++j)if(a[i][j]!=a[i][j-1])l[i][j]=l[i][j-1];
for(int re i=1;i<=n;++i)for(int re j=m-1;j;--j)if(a[i][j]!=a[i][j+1])r[i][j]=r[i][j+1];
for(int re i=1;i<=n;++i)
for(int re x,y,j=1;j<=m;++j){
if(i>1&&a[i][j]!=a[i-1][j])r[i][j]=min(r[i][j],r[i-1][j]),l[i][j]=max(l[i][j],l[i-1][j]),up[i][j]=up[i-1][j]+1;
x=r[i][j]-l[i][j]+1,y=min(x,up[i][j]),mx1=max(mx1,y*y),mx2=max(mx2,x*up[i][j]);
}cout<<mx1<<"\n"<<mx2;
return 0;
}