標籤:逆序數 離散化 樹狀數組 歸併排序法
一篇不錯的講解:http://www.cnblogs.com/shenshuyang/archive/2012/07/14/2591859.html
代碼如下:(樹狀數組+離散化)
#include <cstdio>#include <cstring>#include <iostream>#include <algorithm>using namespace std;const int maxn=500017;int n;int aa[maxn]; //離散化後的數組int c[maxn]; //樹狀數組 struct Node{ int v; int order;}in[maxn]; int Lowbit(int x) //2^k{ return x&(-x);}void update(int i, int x)//i點增量為x{while(i <= n){c[i] += x;i += Lowbit(i);}}int sum(int x)//區間求和 [1,x]{int sum=0;while(x>0){sum+=c[x];x-=Lowbit(x);}return sum;}bool cmp(Node a ,Node b){ return a.v < b.v;}int main(){ int i,j; while(scanf("%d",&n) && n) { //離散化 for(i = 1; i <= n; i++) { scanf("%d",&in[i].v); in[i].order=i; } sort(in+1,in+n+1,cmp); for(i = 1; i <= n; i++) aa[in[i].order] = i; //樹狀數組求逆序 memset(c,0,sizeof(c)); __int64 ans=0; for(i = 1; i <= n; i++) { update(aa[i],1); ans += i-sum(aa[i]);//逆序數個數 }printf("%I64d\n",ans); } return 0;}
代碼如下:(歸併排序法)
int is1[112345],is2[112345];// is1為原數組,is2為臨時數組,n為個人定義的長度__int64 merge(int low,int mid,int high){int i=low,j=mid+1,k=low;__int64 count=0;while(i<=mid&&j<=high)if(is1[i]<=is1[j])// 此處為穩定排序的關鍵,不能用小於is2[k++]=is1[i++];else{is2[k++]=is1[j++];count+=j-k;// 每當後段的數組元素提前時,記錄提前的距離}while(i<=mid)is2[k++]=is1[i++];while(j<=high)is2[k++]=is1[j++];for(i=low;i<=high;i++)// 寫回原數組is1[i]=is2[i];return count;}__int64 mergeSort(int a,int b)// 下標,例如數組int is[5],全部排序的調用為mergeSort(0,4){if(a<b){int mid=(a+b)/2;__int64 count=0;count+=mergeSort(a,mid);count+=mergeSort(mid+1,b);count+=merge(a,mid,b);return count;}return 0;}