【问题标题】:Difficulty understanding code to count the number of inversions using BIT难以理解使用 BIT 计算反转次数的代码
【发布时间】:2020-11-15 00:39:54
【问题描述】:

代码如下:

#include<iostream>
using namespace std;

const int MX = 100;
int n,a[MX*2],bit[MX];

void add(int x, int y){
    for(;x<=n; x+=-x&x) bit[x]+=y;
}
int query(int x){
    int s= 0;
    for(;x>0; x-=-x&x) s+=bit[x];
    return s;
}
int main(){
    ios::sync_with_stdio(0);
    cin.tie(0);
    int ans = 0;
    cin >> n; n*=2;
    for(int i = 0; i<n; i++){
        cin >> a[i];
    }
    for(int i = n-1; ~i; i--){
        ans+=query(a[i]-1);
        add(a[i],1);
    }
    cout << ans;
}

我不明白查询和添加如何有助于查找数组中的反转数。如果有人可以帮助向我解释这一点,那就太好了。谢谢。

【问题讨论】:

  • 这是一个糟糕的混淆代码。不要花时间去理解它。
  • ...如果你想理解它,打印出位模式。

标签: c++ algorithm tree


【解决方案1】:

首先,我希望您了解addqueryBIT 中的工作原理。如果不是,请将BIT 视为一个黑盒,它存储数组A 中元素计数1, 2, ..., n 的前缀总和。例如,A[3] = count(1) + count(2) + count(3)add(x, y)count(x) 增加 yquery(x) 返回总和 count(1) + count(2) + ... + count(x) 即前缀总和直到元素 x

如果i &lt; jarr[i] &gt; arr[j],则索引ij 处的元素形成反转。但是上面的代码以另一种方式读取它; j &gt; iarr[j] &lt; arr[i](这样可以节省对 query 的额外调用)。

现在假设数组是{3, 4, 1, 5, 2} 并且{2, 5, 1} 已经插入到BIT 中。然后是query(1) = 1query(2) = 2query(3) = 2query(4) = 2query(5) = 3(请记住将BIT 视为存储前缀和的黑盒)。注意当索引i指向元素4时,所有已经插入的索引为j1, j2, ..., jk的元素都是&gt; i所以现在我们只需要计算元素的数量&lt; 4是前缀总和直到3,我们通过调用query(3)得到。

【讨论】:

    猜你喜欢
    • 2021-04-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-01-05
    • 2013-07-12
    • 1970-01-01
    相关资源
    最近更新 更多