根据奇偶性,把x,y坐标加起来是奇数的位置翻转一下,就变成求最大01子矩阵了。
然后预处理出每个位置往上最长的01路径,每行用一个单调栈解决。
单调栈从栈底到栈顶维护每一个矩阵的高度和宽度,按高度递增维护。
当前高度如果小于栈顶的高度,那就将栈顶的矩阵更新答案,并且出栈,但是它的宽度是可以为当前高度的矩阵做贡献的,就是当前要加入栈的矩阵的宽度得加上这个要出栈的矩阵。
最后一列做完之后再清一下栈就行了。

#include <bits/stdc++.h>
#define pii pair<int, int>
#define fi first
#define se second
const int N = 2222;
int a[N][N], dp[N][N], n, m, ans1, ans2;
std::pii st[N];
void solve() {
for (int i = 1; i <= n; i++)
for (int j = 1; j <= m; j++)
dp[i][j] = (a[i][j] ? dp[i - 1][j] + 1 : 0);
for (int i = 1; i <= n; i++) {
int top = 0;
for (int j = 1; j <= m + 1; j++) {
int w = 0;
while (top && st[top].fi > dp[i][j]) {
int h = st[top].fi;
w += st[top].se;
top--;
ans1 = std::max(ans1, std::min(w, h) * std::min(w, h));
ans2 = std::max(ans2, w * h);
}
st[++top] = std::pii(dp[i][j], w + 1);
}
}
}
int main() {
scanf("%d%d", &n, &m);
for (int i = 1; i <= n; i++)
for (int j = 1; j <= m; j++) {
scanf("%d", a[i] + j);
if ((i + j) % 2) a[i][j] ^= 1;
}
solve();
for (int i = 1; i <= n; i++)
for (int j = 1; j <= m; j++)
a[i][j] ^= 1;
solve();
printf("%d\n%d\n", ans1, ans2);
return 0;
}
来源:https://www.cnblogs.com/Mrzdtz220/p/12233343.html
