回答“构建三角形”查询的可能性的算法

时间:2018-01-18 20:13:52

标签: algorithm tree

首先,我想为我的英文和标题道歉。问题是我有一个数字A的数组(数组的最大大小是10 ^ 6)。每个数字都小于10 ^ 9。我有10 ^ 5个查询,由两个数字组成:a和b。我必须告诉数组A的[a,b]区间是否有三个数字k1,k2,k3:

  1. k1 + k2> k3
  2. k1 + k3> k2
  3. k2 + k3> K1
  4. (因此可以使用它们构建三角形)。 我知道我可以对一个间隔进行排序并检查它但是它太慢了O(q * n logn)。我认为有必要离线进行这项练习。我考虑过MO的算法,但我不知道如何检查删除元素后是否会是一个三角形。也许任何树结构,但我不知道。你能帮我解决这个问题吗?

    练习链接:https://main.edu.pl/pl/archive/ontak/2009/tro

1 个答案:

答案 0 :(得分:1)

假设我们有一个排序数组a[0], ..., a[k-1]。我们只需要获取每个三元素的邻居元素并检查它是否是一个三角形。检查其他三元组是没有意义的。

如果数组中没有三角形,那么我们肯定知道每2 * a[i] <= a[i+2] i < k-2。我们可以注意到没有三角形的数组元素应该相对快速地增长。

现在让我们构建最糟糕的&#34;排序的数组没有三角形:

1, 1, 2, 3, 5, 8, 13, ... 

看起来很熟悉。 Fibonacci序列。我们的数字不能大于10^9。另一方面,第45个斐波那契数大于10^9

因此,对于长度超过45的每个区间,答案是肯定的。对于较小的间隔,我们可以使用具有O(log(n))插入操作的有序集合数据结构,并且可以从插入位置向前和向后迭代几个步骤(例如,在c ++中为std::set)。或者只是复制这个小间隔,对其进行排序并使用线性搜索检查三角形。

此算法的复杂性为O(q)