我有permutation(P)
个号1
到N (<=10^5)
。假设我可以颠倒排列的子阵列。我必须找到summation(X*Y)
,其中x
是P
可以通过撤消P
和y
的任何子阵列可以采取的形式数量,这些形式的完全反转
例如
if N =2 ; and given permutation = 2 1
Then summation(X*Y) =
if i reverse subarray(1,1) = permutation = 2 1 inversion =1
if i reverse subarray(2,2) = permutation = 2 1 inversions =1
if i reverse subarray(1,2) = permutation = 1 2 inversion =0
summation (x*y) = 2*1 + 1*0 = 2
我的方法是选择每个n*(n+1)/2
子阵列并将其反转,计算其中的反转并进行求和,Complexity= O(n(n+1)/2*nlogn)=O(n^3logn)
是否有O(nlogn)
方法?
https://en.wikipedia.org/wiki/Inversion_(discrete_mathematics)
答案 0 :(得分:0)
tl; dr:修改用于计算反演的标准二进制索引树算法。
在伪代码中,标准算法是
# permutation is p[1..n]
inversions <- 0
let a[1..n] be a zeroed BIT
for i from 1 to n
inversions <- inversions + sum(a[p[i]+1..n]) # sum is O(log n)-time via BIT
a[p[i]] <- 1
end for
我们不是将元素的BIT条目设置为1
,而是将其设置为i
,即可包含该元素的间隔的左端点数。然后我们将总和乘以可能包含当前元素的间隔的右端点数 - 这是将该对反转的间隔数。
# permutation is p[1..n]
inversions <- 0
let a[1..n] be a zeroed BIT
let b[1..n] be a zeroed BIT
for i from 1 to n
inversions <- (inversions
+ sum(b[1..p[i]-1])*(n+1-i) # inversions created by reversal
+ sum(a[p[i]+1..n])*(n+1)*n/2 - sum(b[p[i]+1..n])*(n+1-i)) # inversions not destroyed by reversal
a[p[i]] <- 1
b[p[i]] <- i
end for