2019牛客暑期多校训练营(第二场)H 题解

https://ac.nowcoder.com/acm/contest/882/H

单调栈来找出某个点的左边和右边第一个高度小于自己的位置,然后记录面积并标记这个矩形。

 1 #define bug(x) cout<<#x<<" is "<<x<<endl
 2 #define IO std::ios::sync_with_stdio(0)
 3 #include <bits/stdc++.h>
 4 #define iter ::iterator
 5 using namespace  std;
 6 typedef long long ll;
 7 typedef pair<ll,ll>P;
 8 typedef pair<P,P>P1;
 9 #define mk make_pair
10 #define pb push_back
11 #define se second
12 #define fi first
13 const int N=2e5+5;
14 ll mod=998244353;
15 int n,m;
16 char s[1005][1005];
17 int h[1005][1005];
18 map<pair<int,int>,int>mp;
19 int top;
20 int vis[1000005];
21 struct node{
22     int v,id;
23 }g[1005];
24 int l[1005],r[1005];
25 int main(){
26     scanf("%d%d",&n,&m);
27     for(int i=1;i<=n;i++){
28         scanf("%s",s[i]+1);
29     }
30     for(int i=1;i<=n;i++){
31         for(int j=1;j<=m;j++){
32             if(s[i][j]=='0')h[i][j]=0;
33             else h[i][j]=h[i-1][j]+1;
34         }
35     }
36     for(int i=1;i<=n;i++){
37         mp.clear();
38         top=0;
39         for(int j=1;j<=m;j++){
40             while(top>0&&g[top].v>=h[i][j]){
41                 top--;
42             }
43             if(top==0){
44                 l[j]=0;
45             }
46             else l[j]=g[top].id;
47             g[++top].v=h[i][j];
48             g[top].id=j;
49         }
50         top=0;
51         for(int j=m;j>=1;j--){
52             while(top>0&&g[top].v>=h[i][j]){
53                 top--;
54             }
55             if(top==0){
56                 r[j]=m+1;
57             }
58             else r[j]=g[top].id;
59             g[++top].v=h[i][j];
60             g[top].id=j;
61         }
62 
63         for(int j=1;j<=m;j++){
64             if(h[i][j]<=0)continue;
65             int k=h[i][j]*(r[j]-l[j]-1);
66             if(!mp[mk(l[j],k)]){
67                 mp[mk(l[j],k)]++;
68                 vis[k]++;
69                 int k1=h[i][j]*(r[j]-l[j]-2);
70                 int k2=(h[i][j]-1)*(r[j]-l[j]-1);
71                 if(k1>0)vis[k1]++;
72                 if(k2>0)vis[k2]++;
73             }
74         }
75     }
76     int flag=0;
77     for(int i=1e6;i>=1;i--){
78         while(vis[i]>0){
79             vis[i]--;
80             if(flag){
81                 printf("%d
",i);
82                 return 0;
83             }
84             flag++;
85         }
86     }
87     printf("0
");
88 }
89 /*
90 4 8
91 11111111
92 11111111
93 11111111
94 11111100
95 */
原文地址:https://www.cnblogs.com/ccsu-kid/p/11224830.html