一旦对数组进行排序(O(n log n) 复杂度),查询“LESS(X)”将在log n 时间内运行,因为您可以使用二进制搜索。一旦您知道在位置 k-th 找到元素 X(或找到 A 中的下一个最大元素),您就知道 k 是您的答案(k 个元素小于 X)。
(i, j) 命令意味着数组在紧邻min(A[i]+1, A[j]-1) 的元素和紧随max(A[i], A[j]) 之后的元素之间进行部分重新排序。您可以在 log n、最坏情况 log n + n、时间中找到这些:这接近最坏情况:
k 0 1 2 3 4 5 6 7 8 9 command: (4, 5)
v 7 14 14 15 15 15 16 16 16 18
^ ^
becomes 16 becomes 14 -- does it go before 3 or before 1?
然后重新排序是最坏的情况 n,因为 除了两个元素之外,您的数组几乎已经排序,这意味着使用两次 insertion sort 运行会做得很好。 p>
因此,使用 m 个更新查询和 q 个简单查询,您可以期望拥有
n log n + m*2*(log n + 2*n) + q * log n
复杂性。平均情况(无病态数组,合理稀疏,无病态更新,(j-i) = d
( n + 2m + q ) * log n + 2m*d
这是线性的。在 n = m = q = 10^5 的情况下,您得到的总体复杂度仍低于 10^7,除非您有病态数组和临时查询,在这种情况下,复杂度应该是二次的(甚至可能是三次的;我没有仔细检查过)。
在现实世界的场景中,您还可以想象使用一些技巧。记住 i 和 j 的修改索引的最后一个值,以及最后一个位置查询 k。这花费很少。现在在下一个查询中,您很有可能可以使用这三个值之一来启动您的二分搜索并节省一些时间。