51Nod 1019 逆序数(归并排序)

1019 逆序数 

基准时间限制:1 秒 空间限制:131072 KB 分值: 0 难度:基础题

在一个排列中,如果一对数的前后位置与大小顺序相反,即前面的数大于后面的数,那么它们就称为一个逆序。一个排列中逆序的总数就称为这个排列的逆序数。

如2 4 3 1中,2 1,4 3,4 1,3 1是逆序,逆序数是4。给出一个整数序列,求该序列的逆序数。

Input

第1行:N,N为序列的长度(n <= 50000)
第2 - N + 1行:序列中的元素(0 <= A[i] <= 10^9)

Output

输出逆序数

Input示例

4
2
4
3
1

Output示例

4

逆序数对的归并思路:

这道题用冒泡排序也可以处理,不过因为是n²的算法,对于大数据而言肯定会爆,哎呀,优化版的冒泡也过不了

所以用归并排序的思路,其实也和冒泡的思路一样,只不过归并交换次数,用了另一个来替代,即

当左右两边都有序后,逆序数对其实就是右边 j 位置插入时,左边的数组还剩下多少个未插入,这个就是对于其的逆序数

#include<iostream>

using namespace std;
const int N = 50010;
int a[N],b[N];
int sum = 0, n;

void mergeArray(int left, int right)
{
	for (int i = left; i <= right; i++) 
		b[i] = a[i];
	int mid = (right - left) / 2 + left;
	int j = mid + 1;
	int i = left;
	for (int k = left; k<=right; k++)
	{
		if (i > mid || (j <= right && b[j] < b[i]))
			sum+=mid+1-i, a[k] = b[j++];
		else
			a[k] = b[i++];
	}
}
void mergeSort(int left, int right)
{
	if (left < right)
	{
		int mid = (right - left) / 2 + left;
		mergeSort(left, mid);
		mergeSort(mid + 1, right);
		mergeArray(left,right);
	}
}
int main()
{
	cin >> n;
	for (int i = 0; i<n; i++) {
		scanf("%d", &a[i]);
	}
	mergeSort(0, n - 1);
	printf("%d\n", sum);
	return 0;
}

猜你喜欢

转载自blog.csdn.net/CJ_035/article/details/81279295
今日推荐