查找对的更有效方法

时间:2018-10-07 20:38:54

标签: c++ arrays algorithm

我最近遇到了一个问题,发现要找到一对好的圆。当通过将第一个圆上的任意点 P1 和第二个圆上的 P2 连接起来可以得到给定的距离时,就会形成一对良好的圆。我们得到了 N 个圆和 Q 距离。接下来的 N 行包含圆心的坐标( X Y )及其半径 R 。之后,下一个 Q 列出要检查的距离。

以下约束适用:

2≤ N ≤10 3

1≤ Q ≤5⋅10 5

X Y ≤|2⋅10 5 |

1≤ R ≤2⋅10 5

0≤ K ≤10 6

执行时间必须小于1秒。

在这里, K 是要检查的距离。

删除了我的代码,因为它是正在进行的比赛的一部分

我的代码仅被部分接受,我花了数小时试图为这个问题找到有效的算法。谁能为这个问题提供一种有效的方法,以使TLE得到解决?

1 个答案:

答案 0 :(得分:4)

这是我可能想到的一种可能的解决方案:

  • 遍历每对圆(c 1 ,c 2 )并计算两个值(PS(c 1 , c 2 )与(c 2 ,c 1 ))不相同
    1. 如果c 2 完全位于c 1 内部,则忽略该对。
    2. Value 1 -圆c 1 和c 2 之间的最短距离--< em>其中心之间的距离-r 1 -r 2 用于不相交的圆, 0 用于相交的圆和 r 2 -dist-r 1 ,其中c 1 位于c 2 内部。 li>
    3. Value 2 -增大r 1 的最小值,以使c 1 完全吞并c 2 使得它们根本不相交-这是它们的中心之间的距离+ r 2 -r 1 用于不相交或相交的圆,而 dist + r2 用于休息。
  • 此范围[ Value 1 Value 2 ]定义圆c半径的数量 1 应该增加,使其与c 2 相交,在我们的情况下,c 2 由K定义。如果K属于[ Value 1 Value 2 ],那么我们可以确保在c 1 > 1 和c 2 上的点P 2 ,使得它们之间的距离为K。这是因为如果我们增大c 1 < / sub>在该范围内,它将与c 2 相交。
  • 上述操作的时间复杂度为O(n 2 )。我们可以从所有可能的圆对中收集所有范围,并回答任何查询,我们只需要检查给定K所在的范围。
  • 为了方便查询,我们可以使用二元索引树来存储范围,其中我们在索引 Value 1 处添加+1,在索引( Value 2 + 1)的二进制索引树,然后对于每个查询,我们检查索引K的读取值是否>0。这使我们能够返回O中任何查询的答案(log(K))。构造树的成本为O(N 2 log(K))-包括形成所有成对的圆。
  • 我们还可以使用辅助数组代替二进制索引树来回答O(1)中的查询,如果需要,我愿意讨论其范围。

对于辅助数组方法,初始化一个长度为K的数组,即10 ^ 6,所有元素初始设置为0。现在保留所有Value 1 的最小堆和所有value 1 的最小堆。值Value 2 。 现在,

aux_array = [0, 0, ... ]
curVal = 0
for i in range(0, 10^6):
  while minHeapValue1.root() == i:
     curVal += 1
     minHeapValue1.rootPop()
  while minHeapValue2.root() == i:
     curVal -= 1
     minHeapValue2.rootPop()
  aux_array[i] = curVal

现在,如果aux_array [query_k_value]> 0,则表示存在一个包含query_k_value的范围,否则不包含。

因此,问题的总时间复杂度为O(Qlog(K)+ N 2 log(K))。