POJ 2299

#include <stdio.h>
long a[500005];

long long merge_inversions(long p, long q, long r)
{
	long n1 = q - p + 1;
	long n2 = r - q;
	long *left = new long[n1+1];
	long *right = new long[n2+1];
	long i, j;
	for(i = 0; i < n1; i++)
		left[i] = a[p + i];
	for(j = 0; j < n2; j++)
	    right[j] = a[q + j + 1];
	left[n1] = 1000000000;
	right[n2] = 1000000000;
	i = 0;
	j = 0;
	long long inversions = 0;
	bool counted = false;
	for(long k = p; k <= r; k++)
	{
		if( counted == false &&  left[i] > right[j])
		{
			inversions += (n1 - i);
			counted = true;
		}
		if( left[i] <= right[j] )
		{
			a[k] = left[i];
			i++;
		}
		else 
		{
			a[k] = right[j];
			j++;
			counted = false;
		}
	}
	delete []left;
	delete []right;
	return inversions;
}

long long count_inversions(long p, long r)
{
	long long inversions = 0;
	if( p < r )
	{
		long q = (p + r)/2;
		inversions += count_inversions(p, q);
		inversions += count_inversions(q+1, r);
		inversions += merge_inversions(p, q, r);
	}
	return inversions;
}

int main()
{
	long n;
	while( scanf("%ld", &n) && n != 0 )
	{
		for(long i = 0; i < n; i++)
		{
			scanf("%ld", &a[i]);
		}
		long long count = count_inversions(0, n-1);
		printf("%lld\n", count);
	}
	return 0;
}

归并排序的一个很好的应用~以往多关注快排,想不到在求逆序数方面归并排序的思想如此重要~

这一题让我蛋疼的是,竟然要用longlong存储逆序数。。就这个问题我WA了N久。所以说,数据范围的估算相当重要啊~

posted @ 2011-07-19 22:30  IT屁民  阅读(189)  评论(0编辑  收藏  举报