逆序对(树状数组)

对于数组A,A[i]的逆序对数量为i之前比它大的数的个数。如果已经知道A中的最大值max,当我们顺序的去求A[i]的逆序对的数量的时候,其实就是找此时A中i之前A[i]到max的数有多少个。当然,对于求区间内的事情,树状数组和线段树是最为擅长的。一下代码仅仅考虑A中的元素为正整数的情况,如果数太大或者有负数或者有double的情形需要先离散化处理。

#include <vector>
#include <iostream>
#include <algorithm>
#include <cmath>
using namespace std;

class TreeArray {
 public:
  TreeArray(int size) {
    tree_array_.resize(size + 1, 0);
  }

  int Sum(int pos) {
    int sum = 0;
    while (pos > 0) {
      sum += tree_array_[pos];
      pos -= LowBit(pos);
    }
    return sum;
  }

  void Update(int pos, int increase) {
    while (pos < tree_array_.size()) {
      tree_array_[pos] += increase;
      pos += LowBit(pos);
    }
  }

 private:
  int LowBit(int pos) {
    return pos & (-pos);
  }

 private:
  vector<int> tree_array_;
};

int GetReversePairNum(const vector<int>& arr, int max) {
  TreeArray tree_arr(max);
  int num = 0;
  for (int i = 0; i < arr.size(); ++i) {
    num += tree_arr.Sum(max) - tree_arr.Sum(arr[i]);
    tree_arr.Update(arr[i], 1);
  }
  return num;
}

int main() {
  int a[] = {3,3,2,1,11,13,2,1,7,8};
  // int a[] = {3,3,2};
  vector<int> arr;
  arr.assign(a, a + sizeof(a) / sizeof(int));
  int max_num = 0;
  for (int i = 0; i < arr.size(); ++i) {
    max_num = max(arr[i], max_num);
  }
  cout << GetReversePairNum(arr, max_num) << endl;
  return 1;
}

 

posted @ 2013-08-25 19:21  dmthinker  阅读(202)  评论(0)    收藏  举报