逆序对(线段树)

对于数组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;

struct Node {
  Node(int h, int t) : head(h), tail(t), left(NULL), right(NULL), val(0) {}

  int head;
  int tail;
  Node* left;
  Node* right;
  int val;
};

class SegmentTree {
 public:
  SegmentTree(int h, int t) : head_(h), tail_(t), root_(NULL) {}

  ~SegmentTree() {
    ReleaseNode(root_);
  }

  void ReleaseNode(Node* node) {
    if (!node) return;
    if (node->left) ReleaseNode(node->left);
    if (node->right) ReleaseNode(node->right);
    delete node;
  }

  void Build() {
    root_ = BuildInternal(head_, tail_);
  }

  void Update(int pos, int increase) {
    UpdateInternal(root_, pos, increase);
  }

  int Search(int begin, int end) {
    SearchInternal(root_, begin, end);
  }

  void Debug() {
    if (!root_) {
      cout << "NULL" << endl;
      return;
    }
    cout << root_->head << "\t" << root_->tail << "\t" << root_->val << endl;
  }

 private:
  Node* BuildInternal(int h, int t) {
    if (h > t) return NULL;
    Node* node = new Node(h, t);
    if (h == t) return node;
    node->left = BuildInternal(h, (h + t)/2);
    node->right = BuildInternal((h + t)/2 + 1, t);
    return node;
  }

  void UpdateInternal(Node* node, int pos, int increase) {
    if (!node || pos > node->tail || pos < node->head) {
      return;
    }
    node->val += increase;
    UpdateInternal(node->left, pos, increase);
    UpdateInternal(node->right, pos, increase);
  }

  int SearchInternal(Node* node, int begin, int end) {
    if (!node || begin > node->tail || end < node->head) {
      return 0;
    }

    if (begin <= node->head && end >= node->tail) {
      return node->val;
    }
    int num = 0;
    num += SearchInternal(node->left, begin, end);
    num += SearchInternal(node->right, begin, end);
    return num;
  }

 private:
  Node* root_;
  int head_;
  int tail_;
};

int GetReversePairNum(const vector<int>& arr, int h, int t) {
  SegmentTree seg_t(h, t);
  seg_t.Build();
  int num = 0;
  for (int i = 0; i < arr.size(); ++i) {
    num += seg_t.Search(arr[i] + 1, t);
    seg_t.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;
  int min_num = 0xfffffff;
  for (int i = 0; i < arr.size(); ++i) {
    max_num = max(arr[i], max_num);
    min_num = min(arr[i], min_num);
  }
  cout << min_num << "\t" << max_num << endl;
  cout << GetReversePairNum(arr, min_num, max_num) << endl;
  return 1;
}

 

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