有一个问题,但我找不到有效的算法。
给出一组数字a[1], ..., a[n]
,我们将得到以下类型的查询:
SELECT(i, j, k)
:对a[i], a[i+1], ..., a[j]
排序后,找到[i,j]范围内的第k个最小数字SET(i, value)
:执行a[i] = value
输入:
5 5 // n = 5 (size of array), m = 5 (number of query)
5 10 9 6 7
select 2 4 1
select 2 4 2
set 3 12
set 4 15
select 2 4 1
输出:
6
9
10
我认为我们可以使用Merge Sort Tree
(Special segment tree
)来实现。我在互联网上找到了这个:merge sort tree for range order statistics
但是由于我们可以更改数组值,因此该算法效率不高。
有什么可以帮助我的,我该如何有效实施呢?
谢谢。
答案 0 :(得分:3)
我不了解merge-sort-tree,但是我可以想到不同的数据结构/算法,该数据/算法可以使您在每个查询中以O(n)
的形式输出期望的结果。
此问题的通知解决方案取决于SET
和SELECT
查询之间的分布->我认为还有更多的SELECT
,因此我尝试降低复杂度。如果您有更多SET
,那么我会使用@miradham答案:
david miradham
SET O(n) O(1)
SELECT O(n) O(nlogn)
Space O(n) O(n)
两个解决方案都是O(n)
的空间复杂度。
在您的问题中,您使用的索引从1开始->我将其修改为从0开始。
让我们看看您的示例:a = array (5, 10, 9, 6, 7)
。作为预处理,当括号中的数字为原始数组b = array(5(0), 6(3), 7(4), 9(2), 10(1))
的索引时,我们将创建包含元素的原始索引的排序数组-> a
。可以在O(nlogn)
中完成。
我们如何处理查询?
SELECT(i,j,k):
let cnt = 1;
for m in b (sorted array)
if m(index) <= i && m(index) <= j // the index is in given range
if (cnt == k)
return k // found the k lowest
else cnt++
这是O(n)
,当您遍历b
SET(i,value):
更改a
很容易,可以在O(1)
中完成。更改b
:
originalValue = a[i] // old value
Add [value(i)] to b as new element // O(logn) as b sorted
Remove [originalValue(i)] from b // b sorted but array implementation may cause O(n)
O(n)
的总数
如果需要进一步的解释,请随时提出。希望有帮助!