在高度为500且宽度为10 ^ 5的矩形空间中,我们给出了N个点。
我们应该找出最大的子矩形,其基部位于x轴上,并且不包含其正确内部的任何点(但可以在其边缘包含它们)。
我尝试了一种O(宽度^ 2)算法:
#include <iostream>
#include <algorithm>
const int nWidth = 100000;
const int nHeight = 500;
int main(){
int *nMaxHeights = new int[nWidth];
std::fill (nMaxHeights, nMaxHeights+nWidth, nHeight);
int N;
std::cin >> N;
for (int x,y,iii=0; iii < N; iii++){
std::cin >> x >> y;
nMaxHeights[x] = std::min(y+1, nMaxHeights[x]);
}
int maxArea = 0;
for (int jjj,iii=0; iii < nWidth; iii++){
for (jjj=iii; jjj < nWidth; jjj++){
if (nMaxHeights[jjj] < nMaxHeights[iii])
break;
}
maxArea = std::max((jjj-iii+1)*nMaxHeights[iii],maxArea);
}
std::cout << maxArea;
return 0;
}
它有效,但显然收到TLE(超出执行时间限制)。
我该怎么做得更好?
答案 0 :(得分:0)
有趣的问题。谢谢你指出这些。
我使用了一种算法,可以将O(N)
缩放为较大的N
(点数)和随机分布点。背后的想法:每个矩形都会受到一些点的限制。
以下是python中的一些示例实现http://pastebin.com/068ByYwh,但我不是肯定的,它不包含错误; - )
答案 1 :(得分:0)
想象一下。有三种可能的矩形:在点的下方,左侧和右侧。
我们现在说有两点。让我们先看一下靠近底部的那个。同样,这一步有三种情况。这一点下方有一个矩形。在另一个点的相对侧还有一个矩形。还有另一个点的一面,那里有更多的矩形。
IOW,如果从底部向上看点,那么每个点下面都有一个矩形,这个点将空间分成两个垂直带,每个带有其他点,下面同样有矩形,进一步细分空间。
因此,通过Y和X对点进行排序似乎是合理的(可能通过使它们成为两个排序树的节点,一个按Y排序(因此可以在Y中向上移动)而另一个按X排序(所以你可以移动/搜索左/右)),这是N * log(N),然后递归地访问所有点自下而上,适当地细分空间,看起来像另一个N * log(N)。