poj2299 Ultra-QuickSort (归并排序)

大致题意:给定一串数字,求冒泡排序需要交换的次数。

分析:一个乱序序列的逆序数=只允许相邻两个元素交换的条件下,得到有序序列的交换次数。
归并排序思想:分治
当我们想把一个数组排序的时候,先把这个数组一分为二,然后左部分一分为二,右部分一分为二...
直到细分到每个部分只有一个元素为止。对他们进行简单的归并,然后到上一级,继续归并(就是递归思想),直到最后完成排序。

归并排序细节:归并排序的分:就是递归把数组分得最小。
合:比较a[i]和a[j]的大小,若a[i]≤a[j],则将第一个有序表中的元素a[i]复制到b[k]中,并令i和k分别加上1;
否则将第二个有序表中的元素a[j]复制到b[k]中,并令j和k分别加上1,
如此循环下去,直到其中一个有序表取完,然后再将另一个有序表中剩余的元素复制到r中从下标k到下标t的单元。
归并排序的算法我们通常用递归实现,先把待排序区间[s,t]以中点mid二分,接着把左边子区间排序,再把右边子区间排序,
最后把左区间和右区间用一次归并操作合并成有序的区间[s,t]。

具体代码:

#include <string.h>
#include <stdio.h>
#include <math.h>
#include <algorithm>
#define ll long long
using namespace std;
const int maxn=5e5+10;
int a[maxn],b[maxn];
ll sum;
void merge(int l,int mid,int h)
{
	int i,j,k;
	i=l,j=mid+1,k=l;
	while(i<=mid&&j<=h)
	{
		if (a[i]>a[j])
		{
			sum+=j-k;
			b[k++]=a[j++];
		}
		else
			b[k++]=a[i++];
	}
	while(i<=mid)
		b[k++]=a[i++];
	while(j<=h)
		b[k++]=a[j++];
	for (i=l; i<=h; i++)
		a[i]=b[i];
}
void smerge(int l,int h)
{
	if (l<h)
	{
		int mid=(l+h)/2;
		smerge(l,mid);
		smerge(mid+1,h);
		merge(l,mid,h);
	}
}

int main()
{
	int i,j,n;
	while(~scanf("%d",&n)&&n)
	{
		sum=0;
		for (i=1;i<=n;i++)
		scanf("%d",&a[i]);
		smerge(1,n);
		printf("%lld
",sum);
	}

	return 0;
}

参考博客:https://blog.csdn.net/lmx2014001/article/details/51939325?utm_medium=distribute.pc_relevant_t0.none-task-blog-BlogCommendFromMachineLearnPai2-1.control&depth_1-utm_source=distribute.pc_relevant_t0.none-task-blog-BlogCommendFromMachineLearnPai2-1.control

原文地址:https://www.cnblogs.com/shidianshixuan/p/14353555.html