• [模板] 归并排序 逆序数 分治


    归并排序 

    图来自维基

    2016-07-15_归并排序.gif

    递归调用的过程需要在脑中模拟清楚

    然后是代码的细节问题 

    多复习多理解

    刘汝佳版

    #include <bits/stdc++.h>
    using namespace std;
    const int MAXN = 1e5 + 10;
    
    int ans = 0;
    
    int arr[MAXN] = {0};
    
    int brr[MAXN] = {0};
    
    void mergesort(int *arr, int fst, int lst, int *brr)
    {
    	if(lst - fst > 1)
    	{
    		int mid = fst + (lst - fst) / 2;
    		int p = fst, q = mid, i = fst;
    		
    		mergesort(arr, fst, mid, brr);
    		mergesort(arr, mid, lst, brr);
    		
    		while(p < mid || q < lst)
    		{
    			if(q >= lst || (p < mid && arr[p] <= arr[q]))
    			{
    				brr[i++] = arr[p++];
    			}
    			else
    			{
    				brr[i++] = arr[q++];
    				ans += mid - p;
    			}
    		}
    		for(i = fst; i < lst; i++)
    				arr[i] = brr[i];
    	}
    }
    
    int main()
    {
    	int n;
    	
    	cin>>n;
    	
    	for(int i = 0; i < n; i++)
    		cin>>arr[i];
    		
    	mergesort(arr, 0, n, brr);
    	
    //	for(int i = 0; i < n; i++)
    //		cout<<arr[i]<<'
    ';
    	
    	cout<<ans<<'
    ';
    	
    	return 0;
    }

    //正月点灯笼版

    #include <iostream>
    using namespace std;
    long long ans = 0; //声明逆序数
    void merge(int a[], int L, int M, int R)
    {
    	int leftlen = M - L;
    	int rightlen = R - M + 1;
    	int left[leftlen];
    	int right[rightlen];
    	int i , j , k;
    	for(i = L; i < M; i++)
    	{
    		left[i - L] = a[i];
    	}
    	for(i = M; i <= R; i++)
    	{
    		right[i - M] = a[i];
    	}
    	i = 0; j = 0; k = L;
    	while(i < leftlen && j < rightlen)
    	{
    		if(left[i] < right[j])
    		{
    			a[k++] = left[i++];
    		}
    		else
    		{
    			a[k++] = right[j++];
    			ans += leftlen - i; //求逆序数
    		}
    	}
    	while(i < leftlen)
    	{
    		a[k++] = left[i++];
    	}
    	while(j < rightlen)
    	{
    		a[k++] = right[j++];
    	}
    }
    void merge_sort(int a[], int L, int R)
    {
    	if(L == R)
    		return ;
    	else
    	{
    		int M = (R + L) / 2;
    		merge_sort(a, L, M); //递归分解左侧
    		merge_sort(a, M + 1, R); //递归分解右侧
    		merge(a,L,M + 1,R); //合并
    	}
    }
    int main()
    {
    	ios::sync_with_stdio(false);
    	int a[50010];
    	int n;
    	cin>>n;
    	for(int i = 0; i < n; i++)
    		cin>>a[i];
    	merge_sort(a,0,n - 1);
    	for(int i = 0; i < n; i++)
    	{
    		cout<<a[i]<<endl;
    	}
    	cout<<endl;
    	cout<<ans<<endl;
    	return 0;
    }
  • 相关阅读:
    Android声音和视频播放
    Android使用Pull生成XML
    Android实现图片倒影效果
    Android实现XML解析技术
    Android实现翻页功能原理
    Android实现获取系统应用列表(转)
    mini6410移植全攻略(2)uboot移植之搭建项目框架
    linux下tar.gz、tar、bz2、zip等解压缩、压缩命令小结
    脚本与环境变量设置
    /etc/profile和 . profile 文件
  • 原文地址:https://www.cnblogs.com/zeolim/p/12270709.html
Copyright © 2020-2023  润新知