求排列的逆序数 【归并排序】【分治】【二分】

题目链接  http://cxsjsxmooc.openjudge.cn/2018t2fallsum/011/

思路

1)将数组分成两半,分别求左半边的逆序数和右半边的逆序数

2)求有多少由左半边一个数和右半边一个数组成的逆序数

在归并排序里加一个ans用于统计逆序数就可以了

AC代码

#include <iostream>
#include <cstdlib>
#include <algorithm>
using namespace std;
const int maxn = 100005;
long long int ans = 0;
void Merge_Count(int a[],int s,int m,int e,int temp[])
{
	int left=s;
	int right=m+1;
	int k=0;
	while(left <= m && right <= e) {
		if(a[left] > a[right]) {
			ans += e-right+1;			// 去掉这句程序就是从大到小的归并排序
			temp[k++] = a[left++];
		}
		else
			temp[k++] = a[right++];
	}
	while(left <= m) 
		temp[k++] = a[left++];
	while(right <= e)
		temp[k++] = a[right++];
		
	for(int i=0;i<k;i++)
		a[s++] = temp[i];
}
void MergeSort_Count(int a[],int s,int e,int temp[])		// 排序为从大到小
{
	if(s < e) {
		int mid = s+(e-s)/2;
		MergeSort_Count(a,s,mid,temp);
		MergeSort_Count(a,mid+1,e,temp);
		Merge_Count(a,s,mid,e,temp);
	}	
}
int main()
{
	int n;
	int a[maxn];
	scanf("%d",&n);
	for(int i=0;i<n;i++)
		scanf("%d",&a[i]);

	int temp[maxn];

	MergeSort_Count(a,0,n-1,temp);
	
	cout << ans << endl;		
}

猜你喜欢

转载自blog.csdn.net/weixin_42765557/article/details/84790703
今日推荐