归并排序求逆对数

<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);
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值