UVa 1330 & SMOJ 2706

UVa 1330/POJ 1964

题意

给定1个\(n\times m\)的矩阵,每个字符为'R'或'F'。

你的矩形只能覆盖在'F'上。询问最大的矩形面积。

\(n,m \leq 1000\)

题解

首先预处理每个点向上延伸的最大高度\(height[i][j]\)

再枚举矩形的右下角及其宽度\(width\),高度即为\(min_{k=j-width+1}^{j}height[i][k]\)

时间复杂度\(O(n^3)\),无法通过。

之所以效率低下是因为我们漫无目的地枚举右下角,查找了很多个无用的矩形。

考虑仅枚举出本质不同的极大矩形。所谓极大矩形,是指在特定条件下无法进行扩展的合法矩形。

由于合法矩形的“短板原则”,不妨枚举\((i,j)\)时将\(height[i][j]\)作为高\(h\),则极大情况为\((向左第1个height小于h的位置,向右第1个height小于h的位置)\)

快速求解这2个位置:考虑二分答案,判定可用线段树维护区间\(height\)最小值,或者将合法位置价值视为1,非法视为0,将判定问题转化为矩阵和问题。时间复杂度\(O(n^2log^2n)\)\(O(n^2logn)\)

可以用二分做,自然是具有单调性的,不妨考虑用单调的数据结构进行维护。假设我们维护1个序列,保存左边可能阻碍\(height[i][j]\)的位置。对于序列中的两个位置\(a、b\),若\(a < b\)\(height[i][a] > height[i][b]\),那么\(a\)的阻碍性一定弱于\(b\),没有存在的必要;若\(a < b\)\(height[i][a] < height[i][b]\),则某些情况下\(b\)\(a\)更早地成为阻碍,需要保留。因此,我们只需维护1个下标递增,\(height\)递增的序列(单调栈),即可在\(O(1)\)时间内查询到左边的阻碍位置。右边的阻碍位置也是同理,倒序做即可。

时间复杂度:\(O(n^2)\)。[代码见此](https://github.com/littlewyy/OI/blob/master/poj 1964.cpp)

题外话

在网上看到1种做法:求\(l\)时利用\(l[i-1]\),若\(h[i-1] >= h[i]\)\(l[i] \leq l[i-1]\),故进行迭代,令\(i = l[i-1]\)继续查找;否则\(l[i] = i - 1\)。感觉时间复杂度很不严格,像是骗分。一时又构造不出能Hack掉的数据;似乎一维情况下1234512345形式可以令其变慢,但二维情况下又会少了1些机会。日后再想。


相关题目(加强):SMOJ 2706

题意

给定1个\(n\)\(m\)列,只含'#'或'.'的矩阵。

\(Light[i][j]\):包含\((i,j)\)且不含'#'的矩阵个数

\(\sum_{i = 1}^{n}\sum_{j = 1}^{m}Light[i][j]\)

\(n,m \leq 2000\)

题解

若从每个格子的角度出发,则求包含\((i,j)\)的不同合法矩阵个数。若对每个格子都计算会很麻烦。

题目中要求\(Light\)的总和,那不妨转化1下,从每个合法矩形出发思考。

则答案可转化为所有合法矩形的面积之和。

为了达到平方级别复杂度,我想的是转化成查找出极大矩形,再直接累加极大矩形内的子矩形大小和(可以通过公式\(O(1)\)计算)。但显然,当极大矩形存在重叠时,会重复计数;并且极大矩形间错综复杂,去重也难以实现。

当涉及重复问题时,不妨增加一些限制,降低去重的难度/直接做到不重不漏

不是十分优美的\(O(n^3)\)做法:枚举合法矩形的右下端点\((i,j)\)及其左下端点\((i,k)\),累加此时极大矩形内右下端点为\((i,j)\)的子矩形大小和,并减去与左下端点\((i,k + 1)\)时的极大矩形相交部分的子矩形大小和。若使用单调栈保存相同高度的极大矩形,根本跑不满,在\(SMOJ\)的随(la)机(ji)数据下可以轻松水过。

优美的\(O(n ^ 2)\)做法:(神仙!)枚举横线\(i\),求底边在\(i\)的合法矩形面积和。首先不妨想办法覆盖在这条线的所有子矩形:枚举\((i,j)\)并将其\(Height[i][j]\)作为高求极大矩形,求各个极大矩形内过\((i,j)\)的子矩形面积和,因为每1个子矩形仅属于1个顶到天花板的极大矩形,则仅在天花板的位置进行计数即可;另外,1个子矩形的天花板可能有多处,会在不同的天花板位被重复计数;故假设\(Height[i][a] = Height[i][b]\),应避免横坐标为\(a \rightarrow b\)\(b \rightarrow a\)的子矩形被重复统计:\(b\)的极大矩形不能延伸到\(a\)。具体地,计算极大矩形时,强行令左边的高度必须大于\(Height[i][j]\),右边的高度可以大于等于\(Height[i][j]\),即可做到不重不漏。

窝太菜了QAQ。本题的精妙之处在于

利用天花板保证不漏(即上升到某种方式进行批量计数);

利用强行限制保证不重(有时比容斥好用)。

时间复杂度:\(O(nm)\)代码见此

posted @ 2019-08-08 09:15  littlewyy  阅读(191)  评论(0编辑  收藏  举报