POJ 2299 Ultra-QuickSort

        今晚学习了逆序数,基本上照着别人的程序写的。利用归并排序来统计逆序数。

        当归并两条有序链时,可以同时计算逆序数。

        当left<=i<=mid,mid+1<=j<=right,如果有a[i]>a[j],这样的说明在a的前段中i...mid的元素都比a[j]大,于是逆序数+=mid-i +1;如果a[i]<a[j],这样的发生说明属于正常排序.

        这题如果是用O(n^2)的方法统计会超时,注意要用long long保存,用long会WA

#include <iostream>

#include <cstring>

#include <cstdio>

#define MAX 500005

using namespace std;



long long tmp[MAX];

long long array[MAX];

long long ans;



void merge_sort(int left, int right);

void merge(int left, int mid, int right);





int main()

{

	int n;

	while (cin >> n && n)

	{

		for (int i = 0; i < n; i++)

			scanf("%lld", &array[i]);

		

		ans = 0;		

		merge_sort(0, n-1);

		cout << ans << endl;

	}

	return 0;

}



void merge_sort(int left, int right)

{

	if (left < right)

	{

		int mid = (left + right)/2;

		merge_sort(left, mid);

		merge_sort(mid+1, right);

		merge(left, mid, right);

	}

}



void merge(int left, int mid, int right)

{

	int begin1, begin2;

	int end1, end2;

	int i = 0;



	begin1 = left;

	end1 = mid;

	begin2 = mid+1;

	end2 = right;



	while (begin1 <= end1 && begin2 <= end2)

	{

		if (array[begin1] <= array[begin2])	

			tmp[i++] = array[begin1++];

		else

		{

			tmp[i++] = array[begin2];

			ans += mid - begin1 + 1;   //计算逆序数

			begin2++;

		}	

	}



	while (begin1 <= end1)

		tmp[i++] = array[begin1++];

	

	while (begin2 <= end2)

		tmp[i++] = array[begin2++];

	

	for (int j = 0; j < i; j++)

		array[left+j] = tmp[j];

}

你可能感兴趣的:(Quicksort)