ζ

POJ3494-Largest Submatrix of All 1’s

    题解

题目链接

这是一道比较灵活的单调栈的题目,尽管我在做之前就知道它是单调栈,但还是想了很长一会儿才想到写法。

写单调栈最重要的一点就是弄清要依据什么东西单调。本题看似是求矩形面积,而且矩形与矩形之间还会分隔开,看起来貌似跟单调栈扯不上任何关系。但应该想到:若某一行的某一列出现了一个0,那么在这一列的前面行中不论出现了多少个1,都跟后续的计算无关了,所以可以把这一列已经出现过的数全视为0;出现了1的,就看它之前连续地出现过几个1,这一列的面积就是这一列出现过的1的数量了。

问题就转化成了对于每一列求类似单调栈经典题中的最大矩形了,总的复杂度为。常数非常大,有超时的风险,我TLE了一发,然后马上想到了一个剪枝:对于每一行单调栈的过程中,将0入栈其实没有实际的意义,因此在入栈时判断一下0是否需要入栈即可。加了这个剪枝就过了。

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
#include <iostream>
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <cmath>
#include <algorithm>
#include <map>
#include <set>
#include <queue>
#include <stack>
#include <cctype>
using namespace std;
int n, m;
pair<int, int> p[2005];
int main()
{
while (~scanf("%d%d", &n, &m))
{
int i, j, res = 0;
for (i = 0; i <= m; i++)
p[i].first = p[i].second = 0;
for (i = 1; i <= n; i++)
{
for (j = 1; j <= m; j++)
{
scanf("%d", &p[j].first);
if (p[j].first)
p[j].second++;
else
p[j].second = 0;
}
stack<pair<int, int> > sta;
for (j = 1; j <= m; j++)
{
if (sta.empty() || p[j].second >= sta.top().second)
{
if (p[j].first)
sta.push(p[j]);
continue;
}
pair<int, int> t(0, 0);
while (!sta.empty())
{
if (sta.top().second < p[j].second)
break;
t.first += sta.top().first;
t.second = sta.top().second;
sta.pop();
res = max(res, t.first * t.second);
}
if (p[j].first)
{
t.first += p[j].first;
t.second = p[j].second;
sta.push(t);
}
}
pair<int, int> t(0, 0);
while (!sta.empty())
{
t.first += sta.top().first;
t.second = sta.top().second;
sta.pop();
res = max(res, t.first * t.second);
}
}
printf("%d\n", res);
}
return 0;
}
页阅读量:  ・  站访问量:  ・  站访客数: