洛谷Oj-逆序对-分治(归并排序)
来源:互联网 发布:sql server 权限管理 编辑:程序博客网 时间:2024/06/04 20:03
问题描述:
猫猫TOM和小老鼠JERRY最近又较量上了,但是毕竟都是成年人,他们已经不喜欢再玩那种你追我赶的游戏,现在他们喜欢玩统计。最近,TOM老猫查阅到一个人类称之为“逆序对”的东西,这东西是这样定义的:对于给定的一段正整数序列,逆序对就是序列中ai>aj且i
#define inf 2000000000//无穷大(并不是太专业)#define max 45000//数据规模为40000int L[max/2+2],R[max/2+2];//左子数组,右子数组long merge(int a[],int n,int left,int mid,int right)//合并(merge)函数,数组a,共n个元素,局部数组的开头元素,,局部数组末尾+1的元素{ int i,j,k; long cnt=0;//计数变量 int n1=mid-left;//左闭右开区间[left,mid)的长度 int n2=right-mid;//左开右闭区间[mid,right)的长度 for(i=0;i<n1;i++)//执行n1次for循环 L[i]=a[left+i];//将a[left]到a[left+n1-1](代入n1即得a[mid-1])赋给L[0]到L[n1-1] for(i=0;i<n2;i++)//执行n2次for循环 R[i]=a[mid+i];//将a[mid]到a[mid+n2-1](代入n2即得a[right-1])赋给R[0]到R[n2-1] L[n1]=R[n2]=inf;将L[n1]与R[n2]赋为无穷大 i=0;//重置i j=0;//重置j for(k=left;k<=right-1;k++)//合并子数组L,R。并入数组a中,升序 if(L[i]<=R[j])//如果L[i]小于等于R[j],就将L[i]赋给a[k](k从left到right-1),并将i自增 a[k]=L[i++]; else//如果R[j]小于L[i],就将R[j]赋给a[k](k从left到right-1),并将j自增,这种情况下需要计算逆序对的个数(不存在逆序数的情况是数组L中每一个元素都比数组R中的元素小),我们需要知道在数组L中有几个元素比R[j]大 { a[k]=R[j++]; cnt+=n1-i;i是此时数组a中来自数组L元素的个数,显然比R[j]大的元素的个数就是L[i+1]到L[mid-1]元素的个数,即数组L的大小n1减去i } return cnt;//返回计算变量cnt的值}long mergesort(int a[],int n,int left,int right)//归并排序函数,数组a,共n个元素,局部数组的开头元素,局部数组末尾+1的元素{ long v1,v2,v3;//分别计算三种情况的数目 if(left+1<right)//如果子数组不为空 { int mid=(left+right)/2;//数组的中间位置mid v1=mergesort(a,n,left,mid);//对应情况(1),宏观 v2=mergesort(a,n,mid,right);//对应情况(2),宏观 v3=merge(a,n,left,mid,right);//对应情况(3),宏观 return v1+v2+v3;//三种情况的数目相加并返回 } else return 0;}int main(){ int a[40001],n,i;//n表示数列中有n个数。 scanf("%d",&n);//输入n for(i=1;i<=n;i++)//1下标数组,范围为1到n scanf("%d",&a[i]); printf("%ld\n",mergesort(a,n,1,n+1)); return 0;}
算法描述:
①除了归并排序,冒泡排序也能求解逆序对的个数,只不过会TLE。
②假设我们要统计数列A中逆序对的个数。我们可以将数列A分成两半得到数列B和数列C。于是数列A中所有的逆序对必居下面三者其一:
(1):i,j都属于数列B的逆序对(i,j)。
(2):i,j都属于数列C的逆序对(i,j)。
(3):i属于数列B而j属于数列C的逆序对(i,j)。
③递归的过程就是不断缩小问题规模的过程,递归使得数组不断二分,直到所得子数组中元素个数为1(当子数组中元素个数为0时,函数返回0,所以说最终的状态是子数组元素个数为1的状态),我们不妨从这儿入手,既然左边和右边都已经被完全分割完了,那么就应该执行合并函数了。
合并过程请大家对照来自《挑战程序设计竞赛(第二版)》的归并排序的示意图领悟,在脑海中模拟调用和返回的过程
阅读全文
1 0
- 洛谷Oj-逆序对-分治(归并排序)
- 归并排序 and 逆序对数(分治)
- 逆序对 (归并排序)
- C++ 分治算法-归并排序与逆序对
- 哈理工OJ 2224 逆序对问题(利用归并排序求逆序数对数)
- POJ 2299 分治法求数列逆序对(归并排序)
- 数组中的逆序对——分治法(归并排序的应用)
- 逆序对 归并排序
- 归并排序 & 逆序对
- 归并排序--逆序对
- 九度OJ 1348:数组中的逆序对 (排序、归并排序)
- 九度OJ 1348 数组中的逆序对 -- 归并排序
- 洛谷p1908 逆序对 归并排序
- 笔记1--逆序对(归并排序)
- POJ 2299 逆序对(归并排序)
- 数组中的逆序对(归并排序)
- 求逆序数对(归并排序)
- 求逆序对(归并排序)
- 微信小程序github源码大全下载
- linux内核进程调度系列之调度概述
- Android
- 合并区间
- HGraphBuilder方法分析一
- 洛谷Oj-逆序对-分治(归并排序)
- HttpClient与参数json
- Logcat打印调试信息
- const各种用法总结
- http 请求头信息解释
- 红色警戒2共和国之辉联机教程(兼容到win10)
- 搭建Zookeeper服务器集群
- 研发人员应对需求的言与行
- ant使用ssh和linux交互 如:上传文件