如何有效地回答整数数组中的范围查询?
How to effectively answer range queries in an array of integers?
如何有效地在整数数组中进行范围查询?
查询只有一种类型,即给定范围[a,b]
,找到less than x
的sum of elements
(此处x 是每个查询的一部分,例如 a b x
).
的形式
最初,我尝试从字面上从 a 到 b 并检查当前元素是否小于 x 并相加。但是,这种方式非常低效,因为复杂度为 O(n)。
现在我正在尝试使用线段树并在合并时对数字进行排序。但现在我的挑战是,如果我排序,那么我将失去整数的相对顺序。所以当查询到来时,我不能使用排序数组来获取从 a 到 b 的值。
这里有两种用线段树解决这个问题的方法:
方法一
您可以使用排序数组的线段树。
像往常一样,线段树将您的数组划分为一系列不同大小的子范围。对于每个子范围,您存储条目的排序列表加上排序列表的累积和。然后,您可以使用二进制搜索来查找任何子范围内低于阈值的条目总和。
当给定一个查询时,您首先计算出涵盖 [a,b] 范围的 O(log(n)) 子范围。对于其中的每一个,您都使用 O(log(n)) 二进制搜索。总的来说,这是 O(qlog^2n) 的复杂度来回答 q 个查询(加上预处理时间)。
方法二
你可以使用动态线段树。
线段树允许您在 O(logn) 时间内回答 "Compute sum of elements from a to b" 形式的查询,并且还可以在 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))树来回答问题。
如何有效地在整数数组中进行范围查询?
查询只有一种类型,即给定范围[a,b]
,找到less than x
的sum of elements
(此处x 是每个查询的一部分,例如 a b x
).
最初,我尝试从字面上从 a 到 b 并检查当前元素是否小于 x 并相加。但是,这种方式非常低效,因为复杂度为 O(n)。
现在我正在尝试使用线段树并在合并时对数字进行排序。但现在我的挑战是,如果我排序,那么我将失去整数的相对顺序。所以当查询到来时,我不能使用排序数组来获取从 a 到 b 的值。
这里有两种用线段树解决这个问题的方法:
方法一
您可以使用排序数组的线段树。
像往常一样,线段树将您的数组划分为一系列不同大小的子范围。对于每个子范围,您存储条目的排序列表加上排序列表的累积和。然后,您可以使用二进制搜索来查找任何子范围内低于阈值的条目总和。
当给定一个查询时,您首先计算出涵盖 [a,b] 范围的 O(log(n)) 子范围。对于其中的每一个,您都使用 O(log(n)) 二进制搜索。总的来说,这是 O(qlog^2n) 的复杂度来回答 q 个查询(加上预处理时间)。
方法二
你可以使用动态线段树。
线段树允许您在 O(logn) 时间内回答 "Compute sum of elements from a to b" 形式的查询,并且还可以在 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))树来回答问题。