好一个悬线法!
具体可以去搜一下悬线法的正确性。

#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<algorithm>
#include<cmath>
#define ll long long
#define gc getchar()
using namespace std;
const int N=2e3+5;
template<class o>
inline void qr(o &x)
{
    x=0;char c=gc;
    while(c<'0'||c>'9')c=gc;
    while(c>='0'&&c<='9'){x=x*10+(c^48);c=gc;}
}
void qw(int x)
{
    if(x/10)qw(x/10);
    putchar(x%10+48);
}
int l[N][N],r[N][N],u[N][N],a[N][N];
int main()
{
    int n,m;qr(n),qr(m);
    for(int i=1;i<=n;i++)
        for(int j=1;j<=m;j++)
            qr(a[i][j]),l[i][j]=r[i][j]=j,u[i][j]=1;
    for(int i=1;i<=n;i++)
    {
        for(int j=2;j<=m;j++)
            if(a[i][j]!=a[i][j-1])l[i][j]=l[i][j-1];
        for(int j=m-1;j;j--)
            if(a[i][j]!=a[i][j+1])r[i][j]=r[i][j+1];
    }
    int ans1=0,ans2=0;
    for(int i=1;i<=n;i++)
        for(int j=1;j<=m;j++)
        {
            if(i!=1&&a[i][j]!=a[i-1][j])
                l[i][j]=max(l[i-1][j],l[i][j]),
                r[i][j]=min(r[i-1][j],r[i][j]),
                u[i][j]=u[i-1][j]+1;
            int w=r[i][j]-l[i][j]+1,h=min(w,u[i][j]);
            ans1=max(ans1,h*h);
            ans2=max(ans2,w*u[i][j]);
        }
    qw(ans1),puts("");
    qw(ans2),puts("");
    return 0;
}