2019牛客暑期多校训练营(第八场)A All-one Matrices(单调栈+前缀和)

题目链接:https://ac.nowcoder.com/acm/contest/888/A

题目大意:问有多少个全1的子矩形,且该矩形不会被另外一个全1子矩形覆盖。

解题报告:

  参考博客:https://blog.csdn.net/ccsu_cat/article/details/99087362

  我们预处理每个1的高度以及每一行的前缀和,枚举每一行 i,单调栈求出每个点 j 以h[i][j](1的高度)为高度的矩形左边界L[j]和右边界R[j],然后枚举每个点,如果sum[i + 1][R[j]] - sum[i + 1][L[j] - 1] != R[j] - L[j] + 1,说明这个矩形下面一排不全是1,不会被覆盖,答案++,然后我们要去重,可能有多个点 j,他们形成的矩形是一模一样的,我们再用一个单调栈(维护单调递增的高度)去一下重,如果栈顶元素高度等于当前点高度,说明是重复的,不用计算。

AC代码:

 1 #include<bits/stdc++.h>
 2 #define numm ch-48
 3 #define pd putchar(' ')
 4 #define pn putchar('\n')
 5 #define pb push_back
 6 #define fi first
 7 #define se second
 8 #define fre1 freopen("1.txt","r",stdin)
 9 #define fre2 freopen("2.txt","w",stdout)
10 #define debug cout<<"debug"<<endl
11 using namespace std;
12 template <typename T>
13 void read(T &res) {
14     bool flag=false;char ch;
15     while(!isdigit(ch=getchar())) (ch=='-')&&(flag=true);
16     for(res=numm;isdigit(ch=getchar());res=(res<<1)+(res<<3)+numm);
17     flag&&(res=-res);
18 }
19 template <typename T>
20 void write(T x) {
21     if(x<0) putchar('-'),x=-x;
22     if(x>9) write(x/10);
23     putchar(x%10+'0');
24 }
25 typedef long long ll;
26 const int maxn=3010;
27 const int maxm=505;
28 const int mod=1e9+7;
29 int a[maxn][maxn];
30 int sum[maxn][maxn];    ///每一行的前缀和
31 int h[maxn][maxn];    ///每一行每一列往上的最大高度
32 int L[maxn],R[maxn];
33 ///L[j]:h[i][j]这个高度的矩形的左边界
34 ///R[j]:h[i][j]这个高度的矩形的右边界
35 int main()
36 {
37 //    #define local
38     #ifdef local
39         fre1;
40 //        fre2;
41     #endif // local
42     int n,m;
43     read(n),read(m);
44     for(int i=1;i<=n;i++)
45         for(int j=1;j<=m;j++) {
46             scanf("%1d",&a[i][j]);
47             if(a[i][j])
48                 h[i][j]=h[i-1][j]+1;
49             sum[i][j]=sum[i][j-1]+a[i][j];
50         }
51     int ans=0;
52     for(int i=n;i;i--) {
53         stack<int>sta;
54 //        while(!sta.empty()) sta.pop();
55         sta.push(0);
56         for(int j=1;j<=m;j++) {
57             while(!sta.empty()&&h[i][j]<=h[i][sta.top()]) sta.pop();
58             if(sta.empty()) L[j]=-1;    ///此时h[i][j]=0
59             else L[j]=sta.top()+1;
60             sta.push(j);
61         }
62         while(!sta.empty()) sta.pop();
63         sta.push(m+1);
64         for(int j=m;j;j--) {
65             while(!sta.empty()&&h[i][j]<=h[i][sta.top()]) sta.pop();
66             if(sta.empty()) R[j]=-1;    ///此时h[i][j]=0
67             else R[j]=sta.top()-1;
68             sta.push(j);
69         }
70         while(!sta.empty()) sta.pop();
71         for(int j=1;j<=m;j++) {
72             if(!h[i][j]) {
73                 while(!sta.empty()) sta.pop();
74                 continue;
75             }
76             while(!sta.empty()&&h[i][j]<h[i][sta.top()]) sta.pop();
77             if(sta.empty()||h[i][j]!=h[i][sta.top()]) {
78                 int l=L[j];
79                 int r=R[j];
80                 if(sum[i+1][r]-sum[i+1][l-1]!=r-l+1) ans++;
81                 sta.push(j);
82             }
83         }
84     }
85     write(ans);pn;
86     return 0;
87 }
代码在这里!

 

posted @ 2019-08-14 14:31  wuliking  阅读(150)  评论(0编辑  收藏  举报