逆序数
在一个排列中,如果一对数的前后位置与大小顺序相反,即前面的数大于后面的数,那么它们就称为一个逆序。一个排列中逆序的总数就称为这个排列的逆序数。
如2 4 3 1中,2 1,4 3,4 1,3 1是逆序,逆序数是4。给出一个整数序列,求该序列的逆序数。
Input
第1行:N,N为序列的长度(n <= 50000) 第2 - N + 1行:序列中的元素(0 <= A[i] <= 10^9)
Output
输出逆序数
Input示例
4 2 4 3 1
Output示例
4
利用分治算法从大到小排序!在归并过程中,两个已经排好序的子序列,成对比较 , 如果在前半部分中处理到的位置 大于后半部分处理到的位置 , 那么久加上后半部分中处理到位置 之后的元素数量
例如
5 4 3 1 和 4 3 2 1
当5>4 显然5>3,5>2,5>1 所以直接+4
#include<iostream> #include<cstdio> #include<cmath> #include<cstring> #include<sstream> #include<algorithm> #include<queue> #include<deque> #include<iomanip> #include<vector> #include<cmath> #include<map> #include<stack> #include<set> #include<fstream> #include<memory> #include<list> #include<string> using namespace std; typedef long long LL; typedef unsigned long long ULL; #define MAXN 1000004 #define L 31 #define INF 1000000009 #define eps 0.00000001 /* 求逆序数 分治算法 */ LL a[MAXN],b[MAXN>>1],c[MAXN>>1]; int T, n, cnt; void Merge(int l,int r) { int mid = (l + r) >> 1; for (int i = l; i <= mid; i++) b[i - l + 1] = a[i]; for (int i = mid + 1; i <= r; i++) c[i - mid] = a[i]; int i = 1, j = 1 ,t = l; while (i <= mid - l + 1 && j <= r - mid) { if (b[i] > c[j]) { cnt += (r - j - mid + 1); a[t++] = b[i++]; } else { a[t++] = c[j++]; } } while (i <= mid - l + 1) a[t++] = b[i++]; while (j <= r - mid) a[t++] = c[j++]; return; } void Merge_sort(int l, int r) { if (l < r) { int mid = (l + r) >> 1; Merge_sort(l, mid); Merge_sort(mid + 1, r); Merge(l, r); } } int main() { cnt = 0; scanf("%d", &n); for (int i = 1; i <= n; i++) scanf("%lld", &a[i]); Merge_sort(1, n); printf("%d\n", cnt); //for (int i = 1; i <= n; i++) // printf("%lld", a[i]); return 0; }