如何计算多维数组中的反演?

时间:2016-08-07 04:10:43

标签: arrays algorithm

给定1-D数组说4个元素5 4 2 3,我知道修改的合并排序(分而治之)算法来计算反转的数量(对,使得i 的2个元素

x1 <= x2,
y1 <= y2,
and A[x2][y2] < A[x1][y1].
Say for N = 2
5 4
2 3

反转的数量为4。 对(5,4)(5,2)(5,3)和(4,3)

我是新的堆栈overflow.please原谅格式化问题。

1 个答案:

答案 0 :(得分:1)

使用二进制索引树/ Fenwick树的反转计数

Fenwick Tree是非常有用的数据结构,用于维护每个数据元素的频率和操纵累积频率数据表。

本教程 - BIT - 将为您提供良好的数据结构。它具有所有实现细节。

理解了数据结构后,您可以使用它来计算数组中的反转。假设我们有a[1...n]并且反转被定义为所有对i, j,以便i<j => a[i] > a[j]

最初,所有频率都初始化为0.

for i = n to 1
    res += range-sum(1, a[i]-1)
    insert(a[i])

最后,res将是你的答案。

所花费的时间:O(nlogn)

对于多维,创建多维二进制索引树。上面的教程给出了2D-BIT

的示例

以下是我在上面的教程中的实现:

#define sz(x) ((int)x.size())
#define LSOne(x) (x & -x)
typedef long long LL;
typedef vector<int> vi;
typedef vector<vi> vvi;
typedef pair<int,int> pii;

//Use one based indexing
class FenwickTree{
public:
  vvi ft;
  int n;
  FenwickTree(int _n){
    n=_n;
    ft.assign(n,vi(n,0));
  }
  int rsq(int x,int y){
    int sum=0;
    for(;x;x-=LSOne(x))sum += rsqY(x,y);
    return sum;
  }
  int rsqY(int x,int y){
    int sum=0;
    for(;y;y-=LSOne(y))sum += ft[x][y];
    return sum;
  }
  int rsq(int _x,int _y,int x,int y){
    return rsq(x,y)-rsq(x,_y-1)-rsq(_x-1,y)+rsq(_x-1,_y-1);
  }
  void update(int x,int y,int v){
    for(;x<=n;x+=LSOne(x))updateY(x,y,v);
  }
  void updateY(int x,int y,int v){
    for(;y<=n;y+=LSOne(y))ft[x][y] += v; 
  }
  void clear(){
    ft.assign(n,vi(n,0));
  }
};