[i,j]范围内的第k次统计

时间:2018-12-31 05:14:38

标签: algorithm sorting

有一个问题,但我找不到有效的算法。

问题

给出一组数字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 TreeSpecial segment tree)来实现。我在互联网上找到了这个:merge sort tree for range order statistics

但是由于我们可以更改数组值,因此该算法效率不高。
有什么可以帮助我的,我该如何有效实施呢?
谢谢。

1 个答案:

答案 0 :(得分:3)

我不了解merge-sort-tree,但是我可以想到不同的数据结构/算法,该数据/算法可以使您在每个查询中以O(n)的形式输出期望的结果。

此问题的通知解决方案取决于SETSELECT查询之间的分布->我认为还有更多的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)的总数

如果需要进一步的解释,请随时提出。希望有帮助!