首先,我想为我的英文和标题道歉。问题是我有一个数字A的数组(数组的最大大小是10 ^ 6)。每个数字都小于10 ^ 9。我有10 ^ 5个查询,由两个数字组成:a和b。我必须告诉数组A的[a,b]区间是否有三个数字k1,k2,k3:
(因此可以使用它们构建三角形)。 我知道我可以对一个间隔进行排序并检查它但是它太慢了O(q * n logn)。我认为有必要离线进行这项练习。我考虑过MO的算法,但我不知道如何检查删除元素后是否会是一个三角形。也许任何树结构,但我不知道。你能帮我解决这个问题吗?
答案 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)
。