Rectangles
O(n2) 做法(嘲讽 Sam O(n2logn))。
HDU 2013。
给定 n,m,k 以及 k 个关键点 (Xi,Yi)。求有多少个 1≤x1≤x2≤n,1≤y1≤y2≤m,满足矩形 (x1,y1)(x2,y2) 内部至少有一个关键点。
1≤n,m≤109,1≤k≤1000。
首先我们有一个错误的做法:
对于每一个关键点 (Xi,Yi),计算所有包含这个点的矩形个数,即 XiYi(n−Xi+1)(m−Yi+1) 个矩形。
然后将所有关键点的答案累加。
错误的原因是,一个矩形可能包含多个点,会被重复计算很多次。
于是为了保证不算重,我们在计算关键点 (Xi,Yi) 时,不妨钦定关键点 i 为包含其的矩形中编号最大的。这样每一个矩形就只会在其编号最大的点处被计算。
为了方便,我们将所有关键点按 Xi 为第一关键字,Yi 为第二关键字排序并去重。
那么枚举 i,计算时我就需要计算所有不包含编号 >i 的矩形个数。
接下来有一个错误但是具有启发性的做法:
由于所有不能被矩形包含的关键点都在 i 的右边或者上面,于是我们得出结论:(x1,y1) 可以在 1∼Xi 和 1∼Yi 内随便取(注意这里有问题)。
于是被限制的就只有 (x2,y2) 了。
然后我们又发现,一个编号 j(j>i) 的关键点被包含。当且仅当 x2≥Xj,y2≥Yj,这可以看成是一个矩形覆盖,所有被覆盖的点都不能被选择。
那么我们可以使用单调栈处理这些点的面积并,然后拿总面积减去即可。
然而上面的实际上有问题:对于那些编号 j(j>i) 的且 Yj<Yi 的点,这些点实际上会影响 (x1,y1)!(自己画图)。
具体的,不妨设 x2,y2 已经确定,那么对于那些 j>i 的 j 且 Yj<Yi,那么如果满足 Yj≥y1,那么这个矩形就会包含 j!于是,尽管 x1 没有限制,但是 y1 必须 ≥Yj<Yi∧j>imax{Yj}。
那么在上面处理 x2,y2 的单调栈的过程中,我们需要同步维护一个指针 p 维护所有 Yj<Yi 的 j,以及 p 以前的最大值 M。那么如果上面单调栈得到的 (x2,y2) 的方案数为 S,那么总答案就会累加 SXi(Yi−M)。
这样你就得到了暴打 O(n2logn) 的 O(n2) 做法。