归并排序求逆序对

我们可以这样考虑:

 

归并排序是将数列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。因此,可以在归并

序中的合并过程中计算逆序数.

 

题目:http://poj.org/problem?id=1804


C++代码

#include<iostream>
#include<cstring>
using namespace std;
int a[1001],rr[1001],n,tot;
void merge_sort(int l,int r)
{

 int mid,i,j,k;
 if(l==r) return;
 mid=(l+r)/2;
 merge_sort(l,mid);
 merge_sort(mid+1,r);
 i=l;j=mid+1;k=l;
 while(i<=mid&&j<=r)
 {
     if(a[i]<=a[j]){
     rr[k++]=a[i++];
     }
     else{                 //a[i]>a[j]时 则前半部分比a[i]大的数都比a[j]大
         tot+=mid-i+1;    // 由于此时前半部分a[i]是有序的 则一共有mid-i+1个逆序对
      rr[k++]=a[j++];
     }
 }
     while(i<=mid) rr[k++]=a[i++];
     while(j<=r)   rr[k++]=a[j++];
 for (int i=l;i<=r;i++)
 a[i]=rr[i];
}
int main()
{
 int num=1;
 cin>>n;
 for (int i=1;i<=n;i++)
 {
  int n1;
  cin>>n1;
  memset(a,0,sizeof(a));
  memset(rr,0,sizeof(rr));
  tot=0;                 //初始化
  for(int i=1;i<=n1;i++)
  cin>>a[i];
  merge_sort(1,n1);
  cout<<"Scenario #"<<num<<endl;
  num++;
  cout<<tot<<endl;
 }
}

原文地址:https://www.cnblogs.com/ffhy/p/5661485.html