SPOJ INVCNT - 怎么样?

时间:2013-06-29 21:52:02

标签: c++ algorithm fenwick-tree

任何人都可以帮我完成这项任务http://www.spoj.com/problems/INVCNT/。首先,我尝试用BIT方式思考,但我不能。任何人都可以用BIT解释这个任务的解决方案。 BIT-二进制索引树 C ++

1 个答案:

答案 0 :(得分:5)

假设您知道如何在每个查询的O(log n)中解决以下问题并使用BIT进行更新:

Given an array A[1 .. n], implement the following functions efficiently:
query(x, y) = return A[x] + A[x+1] + ... + A[y]
update(x, v) = set A[x] = v

您可以像这样解决当前的问题:首先,规范化您的数组值。这意味着您必须转换所有值,使它们位于[1, n]区间内。你可以这样做。例如,5, 2, 8将成为2, 1, 3。 (注意:1,2,3是排序顺序为5,2,8的索引)

然后,对于每个i,我们将回答使用元素A[i]生成的j < i次反转次数。为此,我们需要找到i之前大于i的元素数。这相当于query(A[i] + 1, n)

在此查询之后,我们执行update(A[i], 1)

这是如何工作的:我们的BIT数组最初会用零填充。此数组中位置k处的1意味着我们在迭代给定数组时遇到了值k。通过调用query(A[i] + 1, n),我们可以找到有多少个反转A[i]与之前的元素生成,因为我们查询的元素数量是否比我们目前为止迭代的元素大。

找到后,我们需要将A[i]标记为已访问。我们通过更新BIT数组中的位置A[i]并为其添加1来完成此操作:update(A[i], 1)

由于数组中的数字不同于1n,因此您的BIT数组的大小为n,复杂性在n中是对数的。

如果您想了解如何解决最初问题的详细信息,请写一下,尽管这是一个经典之作,您应该可以在Google上轻松找到代码。

注意:此问题还有一个使用您可能想要考虑的merge sort的漂亮解决方案。