如何有效地回答整数数组中的范围查询?

时间:2017-07-14 05:09:28

标签: algorithm segment-tree

如何在整数数组中有效地和范围查询?

查询仅属于一种类型,在给定范围[a,b]的情况下,找到sum of elements less than x(此处x是...的一部分)每个查询,例如a b x)形式。

最初,我尝试从a到b,并检查当前元素是否小于x并加起来。但是,这种方式非常低效,因为复杂性是O(n)。

现在我正在尝试使用分段树并在合并时对数字进行排序。但现在我的挑战是,如果我排序,那么我将失去整数的相对顺序。因此,当查询到来时,我无法使用排序数组从a到b获取值。

1 个答案:

答案 0 :(得分:4)

以下是使用分段树解决此问题的两种方法:

方法1

您可以使用已排序数组的分段树。

与往常一样,段树将您的数组划分为一系列不同大小的子范围。对于每个子范围,您存储条目的排序列表以及排序列表的累积总和。然后,您可以使用二进制搜索在任何子范围内查找低于阈值的条目总和。

当给出查询时,首先计算覆盖[a,b]范围的O(log(n))子范围。对于其中每个,您使用O(log(n))二进制搜索。总的来说,这是回答q查询的O(qlog ^ 2n)复杂度(加上预处理时间)。

方法2

您可以使用动态细分树。

分段树允许您回答表单"从a到b"的计算元素总和的查询。在O(logn)时间内,还可以修改O(logn)中的单个条目。

因此,如果您从空段树开始,则可以按递增顺序重新插入条目。假设我们已经添加了从1到5的所有条目,因此我们的数组可能如下所示:

[0,0,0,3,0,0,0,2,0,0,0,0,0,0,1,0,0,0,4,4,0,0,5,1]

(0表示大于5的条目,因此尚未添加。) 此时,您可以回答任何阈值为5的查询。

总的来说,这将花费O(nlog(n))将所有条目添加到段树中,O(qlog(q))来对查询进行排序,并使用O(qlog(n))来使用段树来回答问题。