学习笔记:归并排序

基本步骤:
1、分界点 mid=(l+r)/2
2、递归排序(left,right)
3、合二为一

#include<cstdio>
#include<cmath>
#include<ctime>
#include<cstring>
#include<iostream>
#include<map>
#include<set>
#include<stack>
#include<queue>
#include<string>
#include<vector>
#define ll long long
#define ull unsigned long long
#define up_b upper_bound
#define low_b lower_bound
#define m_p make_pair
#define mem(a) memset(a,0,sizeof(a))
#define IOS ios::sync_with_stdio(false);cin.tie(0);cout.tie(0)
#define inf 0x3f3f3f3f
#include<algorithm>
using namespace std;

inline ll read()
{
    
    
	ll x=0,f=1; char ch=getchar();
	while(ch<'0'||ch>'9')	{
    
     if(ch=='-') f=-1; ch=getchar(); }
	while('0'<=ch&&ch<='9')	x=x*10+ch-'0', ch=getchar();
	return f*x;
}

const int N = 1e5+5;
int n,a[N],L[N/2+2],R[N/2+2];

void mergesort(int l,int r)
{
    
    
	if(l+1>=r)	return ;
	int mid=l+r>>1;
	mergesort(l,mid); mergesort(mid,r);
	
	int n1=mid-l,n2=r-mid;//n1左边个数,n2右边个数 
	for(int i=0;i<n1;i++)	L[i]=a[l+i];//[l,mid) 
	for(int i=0;i<n2;i++)	R[i]=a[mid+i];//[mid,r)
	L[n1]=R[n2]=inf;//哨兵,处理边界 
	int i=0,j=0;
	for(int k=l;k<r;k++)
	{
    
    
		if(L[i]<=R[j])	a[k]=L[i++];
		else	a[k]=R[j++];
	}
}

int main()
{
    
    
	n=read();
	for(int i=0;i<n;i++)	a[i]=read();
	mergesort(0,n);//[0,n)
	for(int i=0;i<n;i++)	cout<<a[i]<<" ";
	return 0;
}

巧用归并排序:求数组中逆序对的个数
利用归并排序的特性,L数组中的数相对与R数组一定位于原数组的左边,那么如果R中的数小于L中的数就会产生逆序对,又因为L数组和R数组本身是有序的,R中的某个数R[j]小于L中的某个数L[i],那么(L[i],R[j])是一个逆序对,同时R[j]与L[i]后面的数一定也是逆序对,因为L[i]<=L[i+1],而R[j]<L[i],所以R[j]<L[i+1]<=L[i+2]…<=L[n1-1](一直到L数组末尾)
所以R[j]与L数组产生的总共的逆序对数为n1-i;

#include<cstdio>
#include<cmath>
#include<ctime>
#include<cstring>
#include<iostream>
#include<map>
#include<set>
#include<stack>
#include<queue>
#include<string>
#include<vector>
#define ll long long
#define ull unsigned long long
#define up_b upper_bound
#define low_b lower_bound
#define m_p make_pair
#define mem(a) memset(a,0,sizeof(a))
#define IOS ios::sync_with_stdio(false);cin.tie(0);cout.tie(0)
#define inf 0x3f3f3f3f
#include<algorithm>
using namespace std;

inline ll read()
{
    
    
	ll x=0,f=1; char ch=getchar();
	while(ch<'0'||ch>'9')	{
    
     if(ch=='-') f=-1; ch=getchar(); }
	while('0'<=ch&&ch<='9')	x=x*10+ch-'0', ch=getchar();
	return f*x;
}

const int N = 5e5+5;
int n,a[N],L[N/2+2],R[N/2+2];

ll ans=0;
 
void mergesort(int l,int r)
{
    
    
	if(l+1>=r)	return ;
	int mid=l+r>>1;
	mergesort(l,mid); mergesort(mid,r);
	
	int n1=mid-l,n2=r-mid;//n1左边个数,n2右边个数 
	for(int i=0;i<n1;i++)	L[i]=a[l+i];//[l,mid) 
	for(int i=0;i<n2;i++)	R[i]=a[mid+i];//[mid,r)
	L[n1]=R[n2]=inf;//哨兵,处理边界 
	int i=0,j=0;
	for(int k=l;k<r;k++)
	{
    
    
		if(L[i]<=R[j])	a[k]=L[i++];
		else	a[k]=R[j++], ans+=n1-i;
	}
}

int main()
{
    
    
	n=read();
	for(int i=0;i<n;i++)	a[i]=read();
	mergesort(0,n);//[0,n)
//	for(int i=0;i<n;i++)	cout<<a[i]<<" ";
	cout<<ans<<endl;
	return 0;
}

猜你喜欢

转载自blog.csdn.net/m0_50815157/article/details/113422791
今日推荐