contest-888-A 单调栈 前缀

contest-888-A 单调栈 前缀

题意

给一个01矩阵,然后求一个矩阵的最大全1子矩阵数量,这些矩阵要保证,不被其他全一矩阵包含。

思路

官方题解说的很好了,补充:栈里存的高度会要么大于当前up,要么等于当前up,显然等于的时候是不计答案的,大于的时候需要计答案,并且这个矩形的范围其实是从是当前是ij左边的位置开始。(可能和写法有关)。

这样的题目没有想法感觉非常危险。

代码

特别地,我枚举j到m+1可以省一次最后的退栈代码。(注释)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64

#include <bits/stdc++.h>

#define _debug(x) cerr<<#x<<" = "<<x<<endl
using namespace std;
typedef long long ll;
const int MAXN = 3e3 + 59;
typedef long long ll;

int n, m;
struct {
int up, ls;
} stk[MAXN];

int up[MAXN][MAXN]; //consecutive 1 above (i,j) (included)
int pr[MAXN][MAXN]; //pre sum 1 in the left of (i,j) (included)
char str[MAXN];
int top;
ll ans;

int main() {
ios_base::sync_with_stdio(0);
cin.tie(0);

ans = 0;
cin >> n >> m;

for (int i = 1; i <= n; ++i) {
cin >> (str + 1);
for (int j = 1; j <= m; ++j) {
up[i][j] = (str[j] == '1') ? (up[i - 1][j] + 1) : 0;
pr[i][j] = pr[i][j - 1] + (str[j] - '0');
}
}

for (int i = 1; i <= n; ++i) {
top = 0;
for (int j = 1, k; j <= m + 1; ++j) {
k = j;
while (top && stk[top].up >= up[i][j]) {
k = stk[top].ls;
if (stk[top].up > up[i][j]) {
int l = stk[top].ls;
int r = j - 1;
if (pr[i + 1][r] - pr[i + 1][l - 1] != r - l + 1) {
ans++;
}
}
top--;
}
if (up[i][j])stk[++top] = {up[i][j], k};
}
// while (top) {
// int l = stk[top].ls;
// int r = m;
// if (pr[i + 1][r] - pr[i + 1][l - 1] != r - l + 1) {
// ans++;
// }
// top--;
// }
}
cout << ans << endl;
return 0;
}
Your browser is out-of-date!

Update your browser to view this website correctly. Update my browser now

×