入门者笔记·并归排序

并归排序

归并操作(merge),也叫归并算法,指的是将两个顺序序列合并成一个顺序序列的方法。
如 设有数列{6,202,100,301,38,8,1}
初始状态:6,202,100,301,38,8,1
第一次归并后:{6,202},{100,301},{8,38},{1},比较次数:3;
第二次归并后:{6,100,202,301},{1,8,38},比较次数:4;
第三次归并后:{1,6,8,38,100,202,301},比较次数:4;
总的比较次数为:3+4+4=11;
逆序数为14;
时间复杂度:nlog(n);

例题:P1908 逆序对

原题地址

题目描述

猫猫TOM和小老鼠JERRY最近又较量上了,但是毕竟都是成年人,他们已经不喜欢再玩那种你追我赶的游戏,现在他们喜欢玩统计。最近,TOM老猫查阅到一个人类称之为“逆序对”的东西,这东西是这样定义的:对于给定的一段正整数序列,逆序对就是序列中ai>aj且i<j的有序对。知道这概念后,他们就比赛谁先算出给定的一段正整数序列中逆序对的数目。
Update:数据已加强。

输入输出格式

输入格式:
第一行,一个数n,表示序列中有n个数。

第二行n个数,表示给定的序列。序列中每个数字不超过10^9。

输出格式:
给定序列中逆序对的数目。

输入输出样例

输入样例#1:
6
5 4 2 6 3 1
输出样例#1:
11
说明:
对于所有数据,n≤5×10 ^5。

代码:

扫描二维码关注公众号,回复: 5540881 查看本文章
#include<iostream>
#include<cstring>
#include<cmath>
#include<cstdio>
using namespace std;
long long int n;
long long int qq[500050],r[500050],ans=0;
void msort(long long int s,long long int t)
{
	long long int i,k,mid,j;
	if(s==t) return;
	mid=(s+t)/2;
	msort(s,mid);
	msort(mid+1,t);//→→→→→→→递归的体现
	i=s;j=mid+1;k=s;
	while(i<=mid&&j<=t)
	{
		if(qq[i]<=qq[j]) r[k++]=qq[i++];
		else// 出现逆序对
		{
			ans=ans+mid-i+1;
			r[k++]=qq[j++];
		}
	}
	for(;i<=mid;i++) r[k++]=qq[i];
	for(;j<=t;j++) r[k++]=qq[j];
	for(i=s;i<=t;i++)//复制回a数组中 
		qq[i]=r[i];
}
int main()
{
    long long int i;
	scanf("%lld",&n);
	for(i=1;i<=n;i++)
		scanf("%lld",&qq[i]);
	msort(1,n);//从1到n将a数组排序;
	printf("%lld\n",ans);
    return 0;
}

猜你喜欢

转载自blog.csdn.net/weixin_43918350/article/details/88137321