您的位置:首页 > 产品设计 > UI/UE

POJ2299《Ultra-QuickSort》方法:归并排序找逆序数

2013-03-22 13:02 309 查看
题目大意:求一个数的逆序数,比如54321的逆序数为4+3+2+1+0=10,逆序数 = 在只交换相邻两数的前提下,需要的交换次数。

解题思路:因为这题数据量为50W,时间限制为7000ms,用冒泡排序找相邻交换次数肯定超时,因此用归并排序找相邻交换次数。之所以不用快速排序,是因为它不符合相邻元素交换的要求。

// 3748k 2454ms
#include <iostream>

using namespace std;

const int inf = 1000000000;

__int64 ans; // 逆序数

void combine(int *a, int top, int mid, int end)
{
	int len1 = mid-top+1;
	int len2 = end-mid;
	int *left = new int[len1+2];
	int *right = new int[len2+2];
	int i, j, k;
	for (i = 1; i <= len1; ++i)
		left[i] = a[top-1+i];
	left[len1+1] = inf; //inf数参照,必须要加 
	for (j = 1; j <= len2; ++j)
		right[j] = a[mid+j];
	right[len2+1] = inf;
	i = j = 1;
	for (k=top; k <= end; ) {
		if (left[i] <= right[j]) {
			a[k++] = left[i++];
		} else {
			a[k++] = right[j++];
			ans += len1-i+1; //要交换大数的交换次数
		}
	}
	delete left;
	delete right;
}

void mergeSort(int *a, int top, int end) 
{
	if (top < end) {
		int mid = (top+end) / 2;
		mergeSort(a, top, mid);
		mergeSort(a, mid+1, end);
		combine(a, top, mid, end);
	}
}

int main()
{
	//freopen("temp.txt", "r", stdin);
	int n;

	while (cin >> n && n!=0) {
		ans = 0;
		int *a = new int[n+1];
		for (int i = 1;i <= n; ++i) 
			cin >> a[i];
		mergeSort(a, 1, n);
		printf("%I64d\n", ans); //输出64位的整数,无法用cout
		delete a;
	}
	return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: