<pre class="cpp" name="code">给出N个数,你要求出有多少个 (ai,aj) 使得i < j , ai > aj
第一行为整数N(N<=1000000)
第二行为N个整数
输出逆序对个数
逆对数的典型算法有树状数组,归并算法等,我要介绍的就是归并算法 归并排序是分治思想的典型运用,要做的主要有两个部分,将两个已排序的数组按顺序插到一起,这个比较简单,定义一个暂时的数组,然后将较小的储存到里面就好,我们下面的代码中则将暂时数组重新赋值给原来的数组,已保证排序的正常进行(例子是下面的Mergearry函数),第二部分是将数组分治至只有一个元素时就停止,开始合并,运用了递归思想,至于逆序对,举个简单的例子就可以明白,比如归并 2 5 9 和 1 10 11,第一个2和1是逆序对是吧,那和一个数组后面的5 9 肯定也是,这时候加3,然后把1拿出来,重复算count.
#include<iostream>
#include<cstdio>
using namespace std;
int a[1000001];
int temp[1000001];
long long count;
void Mergearry(int first,int mid,int last)
{
int j=first,h=mid+1;
int g=0;
while(j<=mid&&h<=last){
if(a[j]<=a[h]) temp[g++]=a[j++];
else {
temp[g++]=a[h++];
count+=(mid+1-j);//计算逆序对的个数
}
}
while(j<=mid) temp[g++]=a[j++];
while(h<=last) temp[g++]=a[h++];
for(int i=0;i<g;i++){
a[first+i]=temp[i];
}
}//将已经分成两半并排好序的数组的按升序差在一起
void Mergesort(int first,int last){
if(first<last){
int mid=(first+last)/2;
Mergesort(first,mid);
Mergesort(mid+1,last);
Mergearry(first,mid,last);
}
}//将数组分治
int main()
{
int n;
count=0;
scanf("%d",&n);
for(int i=0;i<n;i++)
scanf("%d",&a[i]);
Mergesort(0,n-1);
/*for(int i=0;i<n;i++)
cout << a[i] <<endl;*/
printf("%lld\n",count);
}