在Internet上的搜索引擎常常須要對信息進行比較,好比能夠經過某我的對一些事物的排名來估計他(或她)對各類不一樣信息的興趣,從而實現個性化的服務。ios
對於不一樣的排名結果能夠用逆序來評價它們之間的差別。考慮1,2,…,n的排列i1,i2,…,in,若是其中存在j,k,知足 j < k 且 ij > ik, 那麼就稱(ij,ik)是這個排列的一個逆序。算法
一個排列含有逆序的個數稱爲這個排列的逆序數。例如排列 263451 含有8個逆序(2,1),(6,3),(6,4),(6,5),(6,1),(3,1),(4,1),(5,1),所以該排列的逆序數就是8。顯然,由1,2,…,n 構成的全部n!個排列中,最小的逆序數是0,對應的排列就是1,2,…,n;最大的逆序數是n(n-1)/2,對應的排列就是n,(n-1),…,2,1。逆序數越大的排列與原始排列的差別度就越大。數組
現給定1,2,…,n的一個排列,求它的逆序數。
函數
6 2 6 3 4 5 1
8
/* http://cxsjsxmooc.openjudge.cn/2019t2summerall/011/ 求排列的逆序數 MergeSort 歸併排序 複雜度: n*log(n) */ #define _CRT_SECURE_NO_WARNINGS #include<iostream> using namespace std; long long MergeSort(int a[], int s, int e, int tmp[]); void Merge(int a[], int s, int m, int e, int tmp[]); //int a[] = { 2,6,3,4,5,1 }; //int b[6]; int a[100010]; int b[100010]; int main() { int n; scanf("%d", &n); for (int i = 0; i < n; ++i) scanf("%d", &a[i]); printf("%lld", MergeSort(a, 0, n - 1, b)); return 0; //int size = sizeof(a) / sizeof(int); //long long result = MergeSort(a, 0, size - 1, b); //for (int k = 0; k < size; k++) // cout << a[k] << " "; //cout << "\n" ; //cout << result << endl; //return 0; } /*歸併排序 s :數組開始 e :數組結尾*/ // 將數組 a 的局部 a[s, m] 和 a[m + 1, e] 合併到 tmp, 並保證 tmp 有序,而後再拷貝回 a[s, m] // 歸併操做時間複雜度: O (e-m+1), 即 O (n) long long count(int a[], int s, int m, int e) //從大到小合併[s,m], [m+1,e] { long long result = 0; int p1 = s; int p2 = m + 1; while (p1 <= m && p2 <= e) { if (a[p1] > a[p2]) { result += e - p2 + 1; p1++; } else { p2++; } } return result; } long long MergeSort(int a[], int s, int e, int tmp[]) { long long result = 0; if (s < e) /*當只有一個元素時,遞歸終止,直接調用merge函數,比較 13和27大小,最後排序*/ { int m;// cut array into half m = s + (e - s) / 2; result += MergeSort(a, s, m, tmp);/* 排好序的數組 臨時放在哪裏? */ result += MergeSort(a, m + 1, e, tmp);//分別求兩邊的逆序數 result += count(a, s, m, e);//而後再o(n)算左邊和右邊形成的逆序數 。此時要求左邊和右邊都是從大到小有序的,才能在o(n)時間內算出結果 Merge(a, s, m, e, tmp);//從大到小合併,確保排序 } return result; } void Merge(int a[], int s, int m, int e, int tmp[]) //從大到小合併[s,m], [m+1,e] { int i = 0; int p1 = s; int p2 = m + 1; while (p1 <= m && p2 <= e) { if (a[p1] > a[p2]) { tmp[i++] = a[p1++]; } else { tmp[i++] = a[p2++]; } } while (p1 <= m) tmp[i++] = a[p1++]; while (p2 <= e) tmp[i++] = a[p2++]; for (int j = 0; j < e - s + 1; j++) { a[s + j] = tmp[j]; } }