求逆序對數目___O(nlogn)——分治
阿新 • • 發佈:2018-12-19
設計一個平均時間為的演算法,在個元素的陣列中尋找逆序對數目
這裡介紹分治的思想,用歸併對陣列進行排序,在排序的過程中,即可順便將逆序對數目求出來
首先,不斷地二分這個陣列,直到最小,然後歸併兩邊 歸併時,需要注意的是兩邊的陣列一定是順序的,因為二分陣列已經到最小了,同時,返回後,以後歸併時兩邊剛好是之前已經排好序的部分 同時遍歷一遍左右兩邊,用 和 當做兩邊遍歷的指標,用 作為排序好的陣列的指標 由於兩邊都是排好序的,所以對每個 ,當,第 個到第 個(左邊剩餘的元素)與第 個都滿足逆序,記錄到 中,將記錄到新陣列中,
兩邊遍歷結束之後,若有一邊( 或 )還沒有遍歷完,則直接將剩餘的元素記錄到新陣列中,因為這些元素肯定都是最大的,並且我們也已經記錄了其中逆序的情況(不論是 還是 )
最後排好序的陣列變成原陣列,完成這一次歸併與逆序的統計
#include<bits/stdc++.h> using namespace std; typedef long long ll; int ans; void merge(int a[], int l, int mid, int r) { int i=l, j=mid+1, k=l, temp[10010]; while ((i<=mid) && (j<=r)) if (a[i] <= a[j]) temp[k++] = a[i++]; else { temp[k++] = a[j++]; ans += mid-i+1; } if (i>mid) for(int q=j; q<=r; q++) temp[k++] = a[q]; else for(int q=i; q<=mid; q++) temp[k++] = a[q]; for(int p=l; p<=r; p++) a[p] = temp[p]; } void merge_sort(int a[], int l, int r) { if(l>=r) return; else { int mid = (l+r)/2; merge_sort(a, l, mid); merge_sort(a, mid+1, r); merge(a, l, mid, r); } } int main() { int n, a[10010]; scanf("%d", &n); for(int i=0; i<n; i++) scanf("%d", a+i); merge_sort(a, 0, n-1); printf("%d\n", ans); }