Search for a command to run...
Progressive hints first, then the full explanation and implementation when you're ready to cash out.
Review status
AI-generated and still unreviewed. Double-check the details before internalizing them.
Hints
Open only as much as you need to keep the solve alive.
Fix two rows . A column is useful for this row pair only if both rows have a 1 there. Then any two useful columns form a valid rectangle.
For one fixed row pair, suppose the useful columns are . You only need adjacent pairs . Any rectangle using farther-apart columns is wider, so it is never the unique best for any covered cell.
If , transpose the grid. Then you enumerate pairs in the smaller dimension, giving instead of accidentally cooking your runtime alive.
For each column , keep a DP table : the best area of a minimal rectangle with exact vertical span that covers column .
After filling exact intervals for one column, propagate from larger row intervals to smaller ones: . Then is the answer for cell .
A valid rectangle only cares about its four corners. The inside can be a cursed wasteland of zeroes; nobody asked.
Pick two rows . A column can be a vertical side of a rectangle with these rows iff both and are 1.
So for this row pair, collect all useful columns:
Any two of them make a valid rectangle. But we do not need all pairs.
Key compression
For a fixed row pair, only adjacent useful columns matter:
Why? Take any rectangle using useful columns and with . For any column inside it, there is some adjacent pair with
That adjacent-pair rectangle has the same height and no larger width, so its area is no larger. Therefore the wider rectangle is never needed to get a minimum answer.
This gives a minimal/exhaustive set of rectangles. For every row pair, scan columns once and emit rectangles between consecutive common-1 columns.
Transpose trick
The expensive part is enumerating row pairs. If , transpose the grid and solve the same problem. At the end, transpose the answer back.
Now the working grid has dimensions where
The number of row-pair/column checks is
Since , this is fine.
How to spread rectangle areas to cells
For each working column , define:
minimum area among generated rectangles with exact row span that cover column .
When generating a rectangle with area , it covers every column , so we do:
Now, for a fixed column , if a rectangle covers row interval , it also covers every smaller interval inside it. In particular, it covers each single row with .
So we propagate values from larger intervals to smaller intervals:
if , and
if .
Process intervals by decreasing length, so larger intervals are already finalized before smaller ones use them.
After propagation, is exactly the minimum area of any generated rectangle covering cell . If it is still infinity, no rectangle covers that cell, so output 0.
Correctness
Every generated rectangle is valid because its two chosen rows both contain 1 in its two chosen columns.
Now take any valid rectangle covering some cell . For the row pair , both and are useful columns. Among the useful columns, choose the adjacent pair with . Then is generated, covers , and has width at most . Its height is the same, so its area is no larger.
Thus generated rectangles are enough to achieve the optimum for every cell.
For a fixed column, initializing stores all generated rectangles with exact vertical span . The decreasing-length propagation considers all larger intervals containing each smaller interval. Therefore becomes the minimum area among all generated rectangles whose row span contains and whose column span contains .
By the previous paragraph, that is exactly the required answer.
Complexity
Let and .
Enumeration and DP both take
Memory is in this implementation, which fits the MB limit under the given constraints.
#include <bits/stdc++.h>
using namespace std;
using ll = long long;
void setIO() {
ios::sync_with_stdio(false);
cin.tie(nullptr);
}
int main() {
setIO();
int T;
cin >> T;
const int INF = 1e9;
while (T--) {
int n, m;
cin >> n >> m;
vector<string> g(n);
for (string &row : g) cin >> row;
bool transposed = false;
int R = n, C = m;
vector<string> a = g;
if (R > C) {
transposed = true;
vector<string> b(C, string(R, '0'));
for (int i = 0; i < R; i++) {
for (int j = 0; j < C; j++) {
b[j][i] = a[i][j];
}
}
a.swap(b);
swap(R, C);
}
int pairs = R * (R - 1) / 2;
vector<int> exact((size_t)pairs * C, INF);
int id = 0;
for (int u = 0; u < R; u++) {
for (int d = u + 1; d < R; d++, id++) {
int last = -1;
int h = d - u + 1;
int *cur = exact.data() + (size_t)id * C;
for (int c = 0; c < C; c++) {
if (a[u][c] == '1' && a[d][c] == '1') {
if (last != -1) {
int area = h * (c - last + 1);
for (int x = last; x <= c; x++) {
if (area < cur[x]) cur[x] = area;
}
}
last = c;
}
}
}
}
vector<int> ans((size_t)R * C, 0);
vector<int> dp((size_t)R * R, INF);
for (int col = 0; col < C; col++) {
for (int i = 0; i < R; i++) dp[i * R + i] = INF;
id = 0;
for (int u = 0; u < R; u++) {
for (int d = u + 1; d < R; d++, id++) {
dp[u * R + d] = exact[(size_t)id * C + col];
}
}
for (int len = R; len >= 1; len--) {
for (int u = 0; u + len <= R; u++) {
int d = u + len - 1;
int pos = u * R + d;
int best = dp[pos];
if (u > 0) best = min(best, dp[(u - 1) * R + d]);
if (d + 1 < R) best = min(best, dp[u * R + d + 1]);
dp[pos] = best;
}
}
for (int i = 0; i < R; i++) {
int value = dp[i * R + i];
ans[(size_t)i * C + col] = (value == INF ? 0 : value);
}
}
if (!transposed) {
for (int i = 0; i < n; i++) {
for (int j = 0; j < m; j++) {
if (j) cout << ' ';
cout << ans[(size_t)i * C + j];
}
cout << '\n';
}
} else {
for (int i = 0; i < n; i++) {
for (int j = 0; j < m; j++) {
if (j) cout << ' ';
cout << ans[(size_t)j * C + i];
}
cout << '\n';
}
}
}
}#include <bits/stdc++.h>
using namespace std;
using ll = long long;
void setIO() {
ios::sync_with_stdio(false);
cin.tie(nullptr);
}
int main() {
setIO();
int T;
cin >> T;
const int INF = 1e9;
while (T--) {
int n, m;
cin >> n >> m;
vector<string> g(n);
for (string &row : g) cin >> row;
bool transposed = false;
int R = n, C = m;
vector<string> a = g;
if (R > C) {
transposed = true;
vector<string> b(C, string(R, '0'));
for (int i = 0; i < R; i++) {
for (int j = 0; j < C; j++) {
b[j][i] = a[i][j];
}
}
a.swap(b);
swap(R, C);
}
int pairs = R * (R - 1) / 2;
vector<int> exact((size_t)pairs * C, INF);
int id = 0;
for (int u = 0; u < R; u++) {
for (int d = u + 1; d < R; d++, id++) {
int last = -1;
int h = d - u + 1;
int *cur = exact.data() + (size_t)id * C;
for (int c = 0; c < C; c++) {
if (a[u][c] == '1' && a[d][c] == '1') {
if (last != -1) {
int area = h * (c - last + 1);
for (int x = last; x <= c; x++) {
if (area < cur[x]) cur[x] = area;
}
}
last = c;
}
}
}
}
vector<int> ans((size_t)R * C, 0);
vector<int> dp((size_t)R * R, INF);
for (int col = 0; col < C; col++) {
for (int i = 0; i < R; i++) dp[i * R + i] = INF;
id = 0;
for (int u = 0; u < R; u++) {
for (int d = u + 1; d < R; d++, id++) {
dp[u * R + d] = exact[(size_t)id * C + col];
}
}
for (int len = R; len >= 1; len--) {
for (int u = 0; u + len <= R; u++) {
int d = u + len - 1;
int pos = u * R + d;
int best = dp[pos];
if (u > 0) best = min(best, dp[(u - 1) * R + d]);
if (d + 1 < R) best = min(best, dp[u * R + d + 1]);
dp[pos] = best;
}
}
for (int i = 0; i < R; i++) {
int value = dp[i * R + i];
ans[(size_t)i * C + col] = (value == INF ? 0 : value);
}
}
if (!transposed) {
for (int i = 0; i < n; i++) {
for (int j = 0; j < m; j++) {
if (j) cout << ' ';
cout << ans[(size_t)i * C + j];
}
cout << '\n';
}
} else {
for (int i = 0; i < n; i++) {
for (int j = 0; j < m; j++) {
if (j) cout << ' ';
cout << ans[(size_t)j * C + i];
}
cout << '\n';
}
}
}
}