我们知道,求逆序对最典型的方法就是树状数组,但是还有一种方法就是Merge_sort(),即归并排序。
实际上归并排序的交换次数就是这个数组的逆序对个数,为什么呢?
我们可以这样考虑:
归并排序是将数列a[l,h]分成两半a[l,mid]和a[mid+1,h]分别进行归并排序,然后再将这两半合并起来。
在合并的过程中(设l<=i<=mid,mid+1<=j<=h),当a[i]<=a[j]时,并不产生逆序数;当a[i]>a[j]时,在
前半部分中比a[i]大的数都比a[j]大,将a[j]放在a[i]前面的话,逆序数要加上mid+1-i。因此,可以在归并
排序中的合并过程中计算逆序数.
题目:
题意:给定一个序列a[],每次只允许交换相邻两个数,最少要交换多少次才能把它变成非递降序列.
1 #include2 #include 3 #include 4 5 using namespace std; 6 const int N = 1005; 7 8 int a[N],tmp[N]; 9 int ans;10 11 void Merge(int l,int m,int r)12 {13 int i = l;14 int j = m + 1;15 int k = l; //特别注意,k是从l(字母)开始而不是0;16 while(i <= m && j <= r)17 {18 if(a[i] > a[j])19 {20 tmp[k++] = a[j++];21 ans += m - i + 1;22 }23 else24 {25 tmp[k++] = a[i++];26 }27 }28 while(i <= m) tmp[k++] = a[i++];29 while(j <= r) tmp[k++] = a[j++];30 for(int i=l;i<=r;i++) //一定记得一次归并完成后要把tmp的元素复制给a31 a[i] = tmp[i];32 }33 34 void Merge_sort(int l,int r)35 {36 if(l < r)37 {38 int m = (l + r) >> 1;39 Merge_sort(l,m);40 Merge_sort(m+1,r);41 Merge(l,m,r);42 }43 }44 45 int main()46 {47 int n,T,tt=1;48 scanf("%d",&T);49 while(T--)50 {51 scanf("%d",&n);52 for(int i=0;i
转自:http://blog.csdn.net/acdreamers/article/details/16849761