给定二维平面上的 N (N <= 10 6 ) 个点和一个整数 D (N <= 10 6 ),我们想要找到两个点 p1,p2(p1 右侧的 p2),使得p1.y
并且p2.y
至少为 D 并且p2.x - p1.x
被最小化。
x 和 y 轴在 0..10 6范围内
这是 USACO 过去比赛中的一个问题。
这是我解决它的尝试:
MAXY = N 个点中的最大 y 轴。
假设我们知道 p1,那么我们可以很容易地找到 p2;通过取所有 y 轴在p1.y+D
MAXY 范围内或在 0 到 0 范围内p1.y-D
的点,并取最小 x 轴大于 的点p.x
。这将是 p2 的最佳选择。
但是由于我们不知道 p1,我们将不得不尝试 p1 的所有点,因此应该有效地找到 p2 的最佳选择。
我为此使用了分段树。树中的每个节点都会按照 x 轴的排序顺序存储相应范围内的所有点。在查询时,如果一个节点落在查询范围内,那么我们对数组进行二进制搜索p1.x
并返回大于它的最小元素。
对于 p1 的每一个选择,我们用 0,p1.yD 和 p1.y+D,MAXY 的范围查询树两次,并取两个点中最好的一个。
树的构建可以在 O(NlogN) 时间内完成。每个查询将花费 O(logN*logN) 时间,并且我们进行 N 次查询,因此所花费的总时间为 (Nlogn*logn),它可能不会在 2 秒的时间限制内运行。(10 6 *20*20)。此外,占用的内存将是 O(NlogN),大约为 80 mb (100000*20*4 kb),因为限制为 64 mb,所以太多了。
我们如何才能更快地执行查询并使用更少的空间?