归并排序是效率很好的排序方式,和快排效率一样高,但在稳定性上优于快排,下面我们来介绍归并排序。

归并排序运用递归将序列不断二分(其原理就是分治),就像一棵树不断向下分支,最后分到只剩一个元素,这样这个元素就可当做有序的,因为只有一个元素嘛。然后是合并,怎么分出来就怎么合并回去,不过既然是排序,那么合并的时候就需要比较一下大小了。

下面为了更好的理解,我们来看一张图片。(这张图是借用的,很感谢制图人)

这就是一个简单序列的归并排序过程。

下面让我们来看代码。

#include<cstdio>
const int Max=50001;
int temp[Max],num=0;
void mergearray(int a[],int first,int mid,int last){//将数组按顺序合并
int i=first,j=mid+1,m=mid,n=last,k=0;
while(i<=m&&j<=n){//这里的等号很重要,没有的话前半段的数据不能全部遍历
if(a[i]<=a[j]) temp[k++]=a[i++];
else{
temp[k++]=a[j++];
num+=mid-i+1; //统计逆序数对
}
}
while(i<=m) temp[k++]=a[i++];    //这里等号很重要,不然会漏数据
while(j<=n) temp[k++]=a[j++];//这里等号很重要,不然会漏数据
for(int q=0;q<=last-first;q++)
a[first+q]=temp[q];
} void mergesort(int a[],int first,int last){//将数组二分处理
if(first<last){
int mid=(first+last)/2;
mergesort(a,first,mid); //左边有序
mergesort(a,mid+1,last);//右边有序
mergearray(a,first,mid,last);
}
}
int main()
{
int a[Max],n;
scanf("%d",&n);
for(int i=0;i<n;i++){
scanf("%d",&a[i]);
}
mergesort(a,0,n-1);
for(int i=0;i<n;i++)
printf("%d\n",a[i]);//统计逆序数的话输出num即可。
}

这里可能有的人不太明白逆序数为什么num+=mid-i+1这样算,这里做一下说明,在数组合并时计算前面的数是否比后面的大,这里要注意合并时前后两部分已经是有序,如果此时啊a[i]>a[j],说明a[first]到a[i-1]全部小于a[j],而a[mid+1]到a[j-1]全部小于a[j],那么意思就是大于a[j]的数全部在a[i]到a[mid]之间,a[i]到a[mid]共有mid-i+1个数,所以逆序数对num此时要加上mid-i+1。

本人实力有限,如有错误,欢迎指出,谢谢。

归并排序(包含逆序数对的个数51Nod1019)的更多相关文章

  1. [CF 351B]Jeff and Furik[归并排序求逆序数]

    题意: 两人游戏, J先走. 给出一个1~n的排列, J选择一对相邻数[题意!!~囧], 交换. F接着走, 扔一硬币, 若正面朝上, 随机选择一对降序排列的相邻数, 交换. 若反面朝上, 随机选择一 ...

  2. hiho一下 第三十九周 归并排序求逆序数

    题目链接:http://hihocoder.com/contest/hiho39/problem/1 ,归并排序求逆序数. 其实这道题也是可以用树状数组来做的,不过数据都比较大,所以要离散化预处理一下 ...

  3. poj 2299 Ultra-QuickSort 归并排序求逆序数对

    题目链接: http://poj.org/problem?id=2299 题目描述: 给一个有n(n<=500000)个数的杂乱序列,问:如果用冒泡排序,把这n个数排成升序,需要交换几次? 解题 ...

  4. poj 2299 Ultra-QuickSort :归并排序求逆序数

    点击打开链接 Ultra-QuickSort Time Limit: 7000MS   Memory Limit: 65536K Total Submissions: 34676   Accepted ...

  5. POJ2299 Ultra-QuickSort(归并排序求逆序数)

    归并排序求逆序数   Time Limit:7000MS     Memory Limit:65536KB     64bit IO Format:%I64d & %I64u   Descri ...

  6. HDU 3743 Frosh Week(归并排序求逆序数)

    归并排序求逆序数 #include <iostream> #include <cstdio> using namespace std; #define maxn 1000005 ...

  7. Ultra-QuickSort - poj 2299 (归并排序+统计逆序数)

    利用归并排序统计逆序数,利用归并求逆序在对子序列s1和s2在归并时(s1,s2已经排好序),若s1[i]>s2[j](逆序状况),则逆序数加上s1.length-i,因为s1中i后面的数字对于s ...

  8. hdu 1394 Minimum Inversion Number (裸树状数组 求逆序数 && 归并排序求逆序数)

    题目链接 题意: 给一个n个数的序列a1, a2, ..., an ,这些数的范围是0-n-1, 可以把前面m个数移动到后面去,形成新序列:a1, a2, ..., an-1, an (where m ...

  9. hdu 4911 Inversion (分治 归并排序 求逆序数)

    题目链接 题意:给n个数,求交换k次相邻的数之后的最小的逆序数对. 用分治的方法,以前在poj上做过这种题,昨天比赛的时候忘了.... 下面的归并排序还是以前的模板. #include <ios ...

随机推荐

  1. k-近邻算法原理入门-机器学习

    //2019.08.01下午机器学习算法1——k近邻算法1.k近邻算法是学习机器学习算法最为经典和简单的算法,它是机器学习算法入门最好的算法之一,可以非常好并且快速地理解机器学习的算法的框架与应用.2 ...

  2. SChema 多个属性的设置学习

    <?xml version="1.0" encoding="UTF-8"?> <xs:schema xmlns:xs="http:/ ...

  3. 解决使用还原卡的PC在2个月后要重新加入域的问题

    客户端正确操作: 1. 启动注册表编辑器. 要这样做, 请依次单击 开始 . 运行 , 类型 regedit 在 打开, 框, 然后单击 确定 . 2. 找到并单击以下注册表子项: HKEY_LOCA ...

  4. 浅谈JVM线程调度机制及主要策略

    在之前有说过线程,应该都知道,所谓线程就是进程中的一个子任务,一个进程有多个线程.今天的话主要就是谈一谈JVM线程调度机制.我们结合线程来说,当我们在做多线程的案例时,如一个经典案例,火车站卖票. * ...

  5. ThinkCMF框架上的任意内容包含漏洞

    一.背景 ThinkCMF是一款基于PHP+MYSQL开发的中文内容管理框架,底层采用ThinkPHP3.2.3构建. ThinkCMF提出灵活的应用机制,框架自身提供基础的管理功能,而开发者可以根据 ...

  6. grep -o -E

    sed 命令可以很好的进行行匹配,但从某一行中精确匹配某些内容,则使用 grep 命令并辅以 -o 和 -E 选项可达到此目的.其中 -o 表示“only-matching”,即“仅匹配”之意.光用它 ...

  7. notifix测试

    成功 失败 警告 提示

  8. eshop1-大型电商架构演进

    1. 项目初期 2. 服务器分离 以上的服务分离架构,即使文件服务crash 了,但是application server 和 Database Server 继续可以访问运行 3. 基于并发访问越来 ...

  9. 区块链技术核心概念与原理讲解-Tiny熊

    转载自简书ceido:https://www.jianshu.com/u/fcdf49ef65bb (1)区块链前世今生 密码朋克(Cypherpunk):是一个邮件组,里面有许多大牛. 区块链不是单 ...

  10. Java 用户输入

    章节 Java 基础 Java 简介 Java 环境搭建 Java 基本语法 Java 注释 Java 变量 Java 数据类型 Java 字符串 Java 类型转换 Java 运算符 Java 字符 ...