求01矩阵中次大全1矩阵的面积 (

--------------------------------

1、首先我们知道用栈可以解决直方图中的矩形最大面积问题

2、在这个题目中,如果我们将每一行看作直方图的底,自底向上的连续 1 看成高的话,整个题目就变成了

“求 n 个直方图内所有面积的次大值”。

假设原数组是

所以预处理后原数组变成了

然后遍历行,将这一行的值看成每个位置的高,然后就变成了直方图中矩形最大面积问题了。

3、但我们这里求的是次大面积,并不是最大面积,如果直接将每次的最大面积保存下来取第二大值的话似乎不太行,比如下面这组案例。

我们将这一行看成直方图,矩形长  为2,宽  为1,求得的最大面积是2,所以我们更新最大值为2,但次大值依旧是0,显然这个答案是不对的,因为在直方图中可能只有一个大矩形,但我们题目是可以在大矩形内部取矩形的所以在这里,我们每次更新最大值的时候,除了要把当前算得的面积拿来更新最大值,也要把  和  拿来更新最大值。

----------------------------------------------

如何使用单调栈求解直方图面积

https://blog.csdn.net/qq_41608020/article/details/89294830

------------------------------------------

Code:

#include <bits/stdc++.h>
using namespace std;
int s[1005][1005];
char q[1005];
int maxn1, maxn2;
void calc1(int ans)
{
	if (ans > maxn1)
	{
		maxn2 = maxn1;
		maxn1 = ans;
	}
	else if (ans > maxn2)
		maxn2 = ans;
}
void calc(int x, int y)
{
	calc1(x * y);
	calc1(x * (y - 1));
	calc1((x - 1) * y);
}
int main()
{
	int n, m;
	scanf("%d%d", &n, &m);
	for (int i = 1; i <= n; i++)
	{
		scanf("%s", q);
		for (int j = 1; j <= m; j++)
		{
			s[i][j] = q[j - 1] - '0';
			if (s[i][j] == 1)
				s[i][j] = s[i - 1][j] + 1;
		}
	}
	/*
	for (int i = 1; i <= n; i++)
		for (int j = 1; j <= m; j++)
			printf("%d%c", s[i][j], j == m ? '\n' : ' ');
	*/
	for (int i = 1; i <= n; i++)
	{
		stack<int>st;
		st.push(0);
		s[i][0] = -2;
		s[i][m + 1] = -1;
		for (int j = 1; j <= m + 1; j++)
		{
			while (s[i][st.top()] > s[i][j])
			{
				int index = st.top();
				st.pop();
				calc(j - 1 - st.top(),s[i][index]);
			}
			st.push(j);
		}
	}
	printf("%d", maxn2);
}