- 题目描述:
- 在数组中的两个数字,如果前面一个数字大于后面的数字,则这两个数字组成一个逆序对。输入一个数组,求出这个数组中的逆序对的总数。
- 输入:
-
每个测试案例包括两行:第一行包含一个整数n,表示数组中的元素个数。其中1 <= n <= 10^5。第二行包含n个整数,每个数组均为int类型。
- 输出:
- 对应每个测试案例,输出一个整数,表示数组中的逆序对的总数。
- 样例输入:
-
4 7 5 6 4
- 样例输出:
-
5
总的想法是归并排序,但是在计算逆序对时,有些小问题要考虑,不能漏掉某些元素,一种比较好的做法就在归并时当遇到第一个v[left] > v[right]时,cnt += 所有左边的left以后的元素的个数,而不是cnt += 1。代码如下:
1 #include <iostream> 2 #include <vector> 3 #include <cstdio> 4 using namespace std; 5 6 int n; 7 vector<int> v; 8 unsigned long long cnt; 9 10 void merge(vector<int> &v, int low, int mid, int high) { 11 if (high <= low) return; 12 vector<int> tmp(high - low + 1); 13 int idx1 = low, idx2 = mid + 1; 14 int idx = 0; 15 while (idx1 <= mid && idx2 <= high) { 16 if (v[idx1] > v[idx2]) { 17 tmp[idx++] = v[idx2++]; 18 cnt += mid - idx1 + 1; 19 } else { 20 tmp[idx++] = v[idx1++]; 21 } 22 } 23 24 if (idx1 > mid) 25 while (idx < tmp.size()) tmp[idx++] = v[idx2++]; 26 27 if (idx2 > high) { 28 while (idx < tmp.size()) tmp[idx++] = v[idx1++]; 29 } 30 31 idx = 0; 32 while (idx < tmp.size()) 33 v[low+idx] = tmp[idx++]; 34 } 35 36 37 void mergeSort(vector<int> &v, int low, int high) { 38 if (high <= low) return; 39 int mid = (low + high) / 2; 40 mergeSort(v, low, mid); 41 mergeSort(v, mid + 1, high); 42 merge(v, low, mid, high); 43 } 44 45 int main() { 46 //freopen("a.in", "r", stdin); 47 while (cin >> n) { 48 v.resize(n); 49 cnt = 0; 50 for (int i = 0; i < n; ++i) { 51 cin >> v[i]; 52 } 53 mergeSort(v, 0, v.size() - 1); 54 cout << cnt << endl; 55 } 56 return 0; 57 } 58 /************************************************************** 59 Problem: 1348 60 User: hupo250 61 Language: C++ 62 Result: Accepted 63 Time:200 ms 64 Memory:2500 kb 65 ****************************************************************/