逆序对(线段树)
对于数组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; }
Passion, patience, perseverance, keep it and move on.

浙公网安备 33010602011771号