逆序对(归并排序)

归并排序采用了分治和递归的思想

归并排序入口

void merge_sort(int arr[],int n)
{
	//分配一个辅助数组
	int *tempArr=(int*)malloc(n*sizeof(int));
	if(tempArr)//辅助函数分配成功
	{
		msort(arr,tempArr,0,n-1);
		free(tempArr);
	} 
	else
	printf("error:failed to allocate memory");
}

归并排序

void msort(int arr[],int tempArr[],int left,int right)
 {
 	//如果只有一个元素,那么就不需要继续划分
	//只有一个元素的区域,本身就是有序的,只需要被归并即可
	if(left<right)
	{
		int mid=(left+right)/2;//找中间点
		msort(arr,tempArr,left,mid);//递归划分左半区域
		msort(arr,tempArr,mid+1,right);//递归划分右半区域
		merge(arr,tempArr,left,mid,right);//合并已排序的部分 
	} 
 } 

合并

void merge(int arr[],int tempArr[],int left,int mid,int right)
 {
 	//标记左半区第一个未排序的元素
	 int l_pos=left;
	 //标记右半区第一个未排序的元素
	 int r_pos=mid+1;
	 //临时数组和下标
	 int pos=left;
	 //合并
	 while(l_pos<=mid&&r_pos<=right)
	 {
	 	if(arr[l_pos]<arr[r_pos])//左半区第一个剩余元素更小
		 tempArr[pos++]=arr[l_pos++];
		 else//右半区第一个剩余元素更小
		 tempArr[pos++]=arr[r_pos++]; 
	 } 
	 //合并左半区剩余元素
	 while(l_pos<=mid)
	 tempArr[pos++]=arr[l_pos++];
	 //合并右半区剩余元素
	 while(r_pos<=right)
	 tempArr[pos++]=arr[r_pos++];
	 //把临时数组中合并的元素复制回原来的数组
	 while(left<=right)
	 {
	 	arr[left]=tempArr[left];
	 	left++;
	 } 
 }

模板

#include<bits/stdc++.h>
using namespace std;
//辅助函数,打印数组
void print_arr(int arr[],int n)
{
	for(int i=0;i<n;i++)
	{
		printf("%d ",arr[i]);
	}
	putchar('\n');
}
//合并
void merge(int arr[],int tempArr[],int left,int mid,int right)
 {
 	//标记左半区第一个未排序的元素
	 int l_pos=left;
	 //标记右半区第一个未排序的元素
	 int r_pos=mid+1;
	 //临时数组和下标
	 int pos=left;
	 //合并
	 while(l_pos<=mid&&r_pos<=right)
	 {
	 	if(arr[l_pos]<arr[r_pos])//左半区第一个剩余元素更小
		 tempArr[pos++]=arr[l_pos++];
		 else//右半区第一个剩余元素更小
		 tempArr[pos++]=arr[r_pos++]; 
	 } 
	 //合并左半区剩余元素
	 while(l_pos<=mid)
	 tempArr[pos++]=arr[l_pos++];
	 //合并右半区剩余元素
	 while(r_pos<=right)
	 tempArr[pos++]=arr[r_pos++];
	 //把临时数组中合并的元素复制回原来的数组
	 while(left<=right)
	 {
	 	arr[left]=tempArr[left];
	 	left++;
	 } 
 }
 //归并排序
 void msort(int arr[],int tempArr[],int left,int right)
 {
 	//如果只有一个元素,那么就不需要继续划分
	//只有一个元素的区域,本身就是有序的,只需要被归并即可
	if(left<right)
	{
		int mid=(left+right)/2;//找中间点
		msort(arr,tempArr,left,mid);//递归划分左半区域
		msort(arr,tempArr,mid+1,right);//递归划分右半区域
		merge(arr,tempArr,left,mid,right);//合并已排序的部分 
	} 
 } 
//归并排序入口
void merge_sort(int arr[],int n)
{
	//分配一个辅助数组
	int *tempArr=(int*)malloc(n*sizeof(int));
	if(tempArr)//辅助函数分配成功
	{
		msort(arr,tempArr,0,n-1);
		free(tempArr);
	} 
	else
	printf("error:failed to allocate memory");
}
int main(int argc,char const*argv[])
{
	int arr[]={9,5,7,3,12,4,2,1};
	int n=8;
	print_arr(arr,n);
	merge_sort(arr,n);
	print_arr(arr,n);
	return 0;
	
} 

题目描述

猫猫 TOM 和小老鼠 JERRY 最近又较量上了,但是毕竟都是成年人,他们已经不喜欢再玩那种你追我赶的游戏,现在他们喜欢玩统计。

最近,TOM 老猫查阅到一个人类称之为“逆序对”的东西,这东西是这样定义的:对于给定的一段正整数序列,逆序对就是序列中 ai​>aj​ 且 i<j 的有序对。知道这概念后,他们就比赛谁先算出给定的一段正整数序列中逆序对的数目。注意序列中可能有重复数字。

Update:数据已加强。

输入格式

第一行,一个数 n,表示序列中有 n个数。

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

输出格式

输出序列中逆序对的数目。

输入输出样例

输入 #1复制

6
5 4 2 6 3 1

输出 #1复制

11

说明/提示

对于 25% 的数据,n≤2500

对于 50% 的数据,n≤4×10^4。

对于所有数据,n≤5×10^5

请使用较快的输入输出

应该不会 𝑂(𝑛^2) 过 50 万吧 by chen_zhe

#include<bits/stdc++.h>
using namespace std;
int n,a[10000010],b[10000010];
long long s;
void msort(int left,int right)
{
	if(left==right)
	return ;
	int mid=(left+right)/2;
	int l_pos=left;
	int r_pos=mid+1;
	int pos=left;
	msort(left,mid);//递归划分左半区域 
	msort(mid+1,right);//递归划分右半区域
	while(l_pos<=mid&&r_pos<=right)
	{
		if(a[l_pos]<=a[r_pos])//左半区第一个剩余元素更小
		b[pos++]=a[l_pos++];
		else//右半区第一个剩余元素更小
		{
			b[pos++]=a[r_pos++];
			s+=mid-l_pos+1;
		}
		
	} 
	//合并左半区剩余元素 
	while(l_pos<=mid)
	b[pos++]=a[l_pos++];
	//合并右半区剩余元素 
	while(r_pos<=right)
	b[pos++]=a[r_pos++];
	for(int i=left;i<=right;i++)
	a[i]=b[i];
}
int main()
{
	cin>>n;
	for(int i=1;i<=n;i++)
	cin>>a[i];
	msort(1,n);
	printf("%lld",s);
	return 0;
}

  • 7
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值