第二场已经做过一个类似的了,到这里只是稍微变了一下。
链接
题意
给你一个01矩阵,让求全1矩阵的个数,但是这些矩阵中不能互相有包含关系。
思路
我们可以先用基本的单调栈求出每个(i,j)点左延伸和右延伸的地方。至于判断的话,我们想一下,所有的包含也就是上下包含和左右包含,不管多么复杂的矩阵包含无外乎都是这样的,然后左右包含,我们就看看这一行中的左延伸点和右延伸点是否相同就行,上下包含,就需要看$$l[i][j]与l[i+1][j] ,r[i][j] 与 r[i+1][j], h[i][j]与h[i+1][j] $$的关系了。
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 65 66 67 68 69 70 71 72 73 74 75 76 77 78
| #include <iostream> #include <algorithm> #include <stdio.h> #include <string> #include <cstring> #include <math.h> #include <stack> using namespace std; int dp[3005][3005];
struct node{ int pos, h; }; int vis[3005][3005]; int l[3005][3005]; int r[3005][3005];
int main() { int n , m; cin >> n >> m; int tot = 0, cnt = 0; for(int i = 1; i <= n ;++i) { for(int j = 1; j <= m; ++j) { char c; cin >> c; if(c == '0') dp[i][j] = 0; else{ dp[i][j] = dp[i - 1][j] + 1; } }
} for(int i = 1; i <= n; ++i) { stack<node>S; for(int j = 1; j <= m; ++j) { while(!S.empty() && S.top().h >= dp[i][j]) { S.pop(); } if(S.size() == 0) l[i][j] = 1; else l[i][j] = S.top().pos + 1; S.push({j,dp[i][j]}); } while(!S.empty())S.pop(); for(int j = m; j >= 1; --j) { while(!S.empty() && S.top().h >= dp[i][j]) { S.pop(); } if(S.size() == 0) r[i][j] = m; else r[i][j] = S.top().pos - 1; S.push({j,dp[i][j]}); } } int ans = 0; for(int i = 1; i <= n; i++) { for(int j = 1; j <= m; j++) { if(dp[i][j] == 0 || l[i][j] == l[i+1][j] && r[i][j] == r[i + 1][j] && dp[i + 1][j] == dp[i][j] + 1 || vis[ l[i][j] ][ r[i][j]] == i) { continue; } vis[ l[i][j] ][ r[i][j]] = i; ans ++; } } cout << ans << '\n'; }
|