题意:给你一个只包含0和1的n×m大小的矩阵,问你第二大的全为1的矩形有多大。(不严格第二大)
题解:每个矩阵的大小由长和宽决定,矩形的长对应原矩阵中每一行最多有多少个元素,他们向上扩展的连续“1”的数量一样,矩形的宽对应向上扩展的连续“1”的数量。我们从第一行开始枚举,一开始先更新该行所有元素向上扩展最多有多少个连续“1”,设为c[j]数组,然后用一个单调递增的栈维护该行的c[j]数组,找出该行每个元素以自己为最小值,向左向右分别最远扩展到哪里,这里就有l[i],r[i]数组,此时最大的矩形面积应为(r[i]-l[i]+1)* c[j],第二小的值是max((r[i]-l[i])* c[j],(r[i]-l[i]+1) * (c[j] - 1)),然后不断更新最大值和第二大值,最后的第二大值就是答案。
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>
#include <stack>
using namespace std;
const int maxn = 1005;
char a[maxn][maxn];
int c[maxn],l[maxn],r[maxn];
void update(int &mx,int &mmx,int x)
{
if(x <= mmx)
return;
if(x <= mx)
{
mmx = x;
return;
}
mmx = mx;
mx = x;
}
int main()
{
int n,m;
scanf("%d%d",&n,&m);
int mx = 0,mmx = 0;
for(int i=0; i<n; i++)
{
scanf("%s",a[i]);
}
for(int i=0; i<n; i++)
{
for(int j=0; j<m; j++)
{
if(a[i][j] == '1')
c[j]++;
else
c[j] = 0;
l[j] = j;
r[j] = m-1;
}
stack<int> s;
for(int j=0; j<m; j++)
{
while(!s.empty() && c[j] <= c[s.top()])
{
l[j] = l[s.top()];
r[s.top()] = j-1;
s.pop();
}
s.push(j);
}
int mx1 = 0,mmx1 = 0;
for(int j=0; j<m; j++)
{
int x = r[j] - l[j] + 1,y = c[j];
update(mx1,mmx1,x*y);
update(mx1,mmx1,(x-1)*y);
update(mx1,mmx1,x*(y-1));
}
update(mx,mmx,mx1);
update(mx,mmx,mmx1);
}
printf("%d",mmx);
}