【基礎】1019 逆序數
阿新 • • 發佈:2018-11-10
一個一個比,資料太大就會超時。程式碼如下:
#include<iostream> using namespace std; int a[50005]; int main(){ int n; long long ans=0; cin>>n; for(int i=0;i<n;i++) cin>>a[i]; for(int i=0;i<n-1;i++) for(int j=i+1;j<n;j++) if(a[i]>a[j]) ans++; cout<<ans<<endl; return 0; }
利用歸併排序,程式碼如下:
#include<iostream> #include<algorithm> using namespace std; const int n=50005; int arr[n],brr[n];// arr為原陣列,brr為臨時陣列,n為個人定義的長度 long merge(int low,int mid,int high) { int i=low,j=mid+1,k=low; long count=0; while(i<=mid&&j<=high) if(arr[i]<=arr[j])// 此處為穩定排序的關鍵,不能用小於 brr[k++]=arr[i++]; else { brr[k++]=arr[j++]; count+=j-k;// 每當後段的陣列元素提前時,記錄提前的距離 } while(i<=mid) brr[k++]=arr[i++]; while(j<=high) brr[k++]=arr[j++]; for(i=low;i<=high;i++)// 寫回原陣列 arr[i]=brr[i]; return count; } long mergeSort(int a,int b)// 下標,例如陣列int arr[5],全部排序的呼叫為mergeSort(0,4) { if(a<b) { int mid=(a+b)/2; long count=0; count+=mergeSort(a,mid); count+=mergeSort(mid+1,b); count+=merge(a,mid,b); return count; } return 0; } int main(){ int n; cin>>n; for(int i=0;i<n;i++) cin>>arr[i]; cout<<mergeSort(0,n-1)<<endl; return 0; }
最難理解的是: count+=j-k;// 每當後段的陣列元素提前時,記錄提前的距離
拿陣列 陣列 2 4 3 1 遞迴【分】
注意:每層遞迴arr的值會變,左右兩邊按照從小到大排序。
2 4 | 1 3
2 4 | 3 1
可以這樣理解:
陣列:2431
第一次1前移1位,2413
第二次1前移2位,1243
第三次3前移1位,1234
把提前的距離相加,得到逆序數。