1. 程式人生 > >逆序數

逆序數

scan memory () star F12 輸出 空間限制 ble 基礎

1019 逆序數技術分享 基準時間限制:1 秒 空間限制:131072 KB 分值: 0 難度:基礎題 技術分享 收藏 技術分享 關註 在一個排列中,如果一對數的前後位置與大小順序相反,即前面的數大於後面的數,那麽它們就稱為一個逆序。一個排列中逆序的總數就稱為這個排列的逆序數。 如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; }

逆序數