Skip to content

Commit 6eb177b

Browse files
Merge pull request #4557 from brebenelmihnea/maximum-building-2
[Editorial] Maximum Building II
2 parents 1828518 + 6f98889 commit 6eb177b

File tree

2 files changed

+108
-1
lines changed

2 files changed

+108
-1
lines changed

content/4_Gold/Stacks.problems.json

+1-1
Original file line numberDiff line numberDiff line change
@@ -196,7 +196,7 @@
196196
"isStarred": false,
197197
"tags": ["Stack"],
198198
"solutionMetadata": {
199-
"kind": "none"
199+
"kind": "internal"
200200
}
201201
},
202202
{

solutions/gold/cses-1148.mdx

+107
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,107 @@
1+
---
2+
id: cses-1148
3+
source: CSES
4+
title: Maximum Building II
5+
author: Mihnea Brebenel
6+
---
7+
8+
## Explanation
9+
10+
Let $r_{i,j}$ be the maximum number of continuous free cells on line $i$ starting from $(i, j)$ to the right.
11+
This can be precomputed.
12+
Similarly to [Maximum Building I](https://cses.fi/problemset/task/1147), we can also apply monotonic stacks to find
13+
1. $u_{i, j}$, the last line above $i$ with cell $(x, j)$ such that $r_{x, j} > r_{i, j}$
14+
2. $d_{i, j}$, the last line under $i$ with cell $(y, j)$ such that $r_{y, j} \ge r_{i, j}$
15+
16+
We can efficiently update the answer matrix with [prefix sums](/silver/more-prefix-sums#2d-prefix-sums)
17+
and [difference arrays](https://codeforces.com/blog/entry/78762).
18+
Having $r_{i,j}$, $u_{i,j}$ and $d_{i,j}$ precomputed, we know the upper bound
19+
and the lower bound of the rectangle of width $r_{i,j}$,
20+
i.e. how much it can expand above and below line $i$ maintaing width $r_{i, j}$.
21+
22+
We'll do difference arrays on each column independently.
23+
Accordingly, the updates of the answer matrix look like this:
24+
- increment $\texttt{ans}[1][r_{i,j}]$ by $1$
25+
- decrement $\texttt{ans}[i - u_{i, j} + 2][r_{i,j}]$ by $1$
26+
- decrement $\texttt{ans}[d_{i,j} - i + 2][r_{i, j}]]$ by $1$
27+
- increment $\texttt{ans}[d_{i,j} - u_{i,j} + 3][r_{i,j}]$ by $1$
28+
29+
Finally, we add $ans[i][j]$ to $ans[i][j-1]$ i.e. a submatrix of size
30+
$i \times j$ contains a submatrix of size $i \times (j-1)$.
31+
32+
## Implementation
33+
34+
**Time Complexity:** $\mathcal{O}(N \cdot M)$
35+
36+
<LanguageSection>
37+
<CPPSection>
38+
39+
```cpp
40+
#include <iostream>
41+
#include <stack>
42+
#include <vector>
43+
44+
using namespace std;
45+
46+
int main() {
47+
int n, m;
48+
cin >> n >> m;
49+
vector<vector<int>> r(n + 2, vector<int>(m + 2));
50+
vector<vector<int>> u(n + 1, vector<int>(m + 1));
51+
vector<vector<int>> d(n + 1, vector<int>(m + 1));
52+
vector<vector<int>> ans(n + 3, vector<int>(m + 3));
53+
vector<vector<char>> mat(n + 1, vector<char>(m + 1));
54+
for (int i = 1; i <= n; i++) {
55+
for (int j = 1; j <= m; j++) { cin >> mat[i][j]; }
56+
for (int j = m; j >= 1; j--) {
57+
if (mat[i][j] == '*') {
58+
r[i][j] = 0;
59+
} else {
60+
r[i][j] = r[i][j + 1] + 1;
61+
}
62+
}
63+
}
64+
65+
stack<int> st;
66+
// Precompute u[i][j] and d[i][j]
67+
for (int j = 1; j <= m; j++) {
68+
while (!st.empty()) { st.pop(); }
69+
for (int i = 1; i <= n; i++) {
70+
while (!st.empty() && r[i][j] < r[st.top()][j]) { st.pop(); }
71+
u[i][j] = st.empty() ? 1 : (st.top() + 1);
72+
st.push(i);
73+
}
74+
while (!st.empty()) { st.pop(); }
75+
for (int i = n; i >= 1; i--) {
76+
while (!st.empty() && r[i][j] <= r[st.top()][j]) { st.pop(); }
77+
d[i][j] = st.empty() ? n : (st.top() - 1);
78+
st.push(i);
79+
}
80+
}
81+
82+
// Make difference array on each column independently
83+
for (int i = 1; i <= n; i++) {
84+
for (int j = 1; j <= m; j++) {
85+
ans[1][r[i][j]]++;
86+
ans[i - u[i][j] + 2][r[i][j]]--;
87+
ans[d[i][j] - i + 2][r[i][j]]--;
88+
ans[d[i][j] - u[i][j] + 3][r[i][j]]++;
89+
}
90+
}
91+
for (int j = 1; j <= m; j++) {
92+
for (int i = 1; i <= n; ++i) { ans[i][j] += ans[i - 1][j]; }
93+
for (int i = 1; i <= n; ++i) { ans[i][j] += ans[i - 1][j]; }
94+
}
95+
for (int i = n; i >= 1; i--) {
96+
for (int j = m; j >= 2; --j) { ans[i][j - 1] += ans[i][j]; }
97+
}
98+
99+
for (int i = 1; i <= n; i++) {
100+
for (int j = 1; j <= m; ++j) { cout << ans[i][j] << " "; }
101+
cout << '\n';
102+
}
103+
}
104+
```
105+
106+
</CPPSection>
107+
</LanguageSection>

0 commit comments

Comments
 (0)