求逆序对 (用归并) nlogn
来源:互联网 发布:mac免费打谱软件 编辑:程序博客网 时间:2024/05/21 10:42
逆序对 在线测评 洛谷:
https://www.luogu.org/problem/show?pid=1908
什么是逆序对??
对于一个包含N个非负整数的数组A[1..n],如果有i < j,且A[ i ]>A[ j ],则称(A[ i] ,A[ j] )为数组A中的一个逆序对。(来自百度百科)
怎么求 有一个广为人知的 n方 的算法 就是枚举
在此讲一下 用归并排序 复杂度是nlogn的算法
贴代码:
#include<iostream>#include<cstdio>using namespace std;const int INF=40010;int a[INF];int t[INF];int cnt;void mid_sort(int x,int y){ if(y-x>1)//我们排序的是[x,y)的 所以当y-x为一时就只剩下一个数了 此时 我们就没有必要給一个数排序了 { int m;// m时x和y中点 m=x+(y-x)/2; int l=x; int r=m; int i=x; mid_sort(x,m);/*这是递归来排序*/ mid_sort(m,y);//同上 while(l<m||r<y) //从这里往下是归并排序中的 合并两串已经排好序的数 { if(r>=y||(l<m && a[l]<=a[r])) t[i++]=a[l++]; else{ t[i++]=a[r++]; cnt+=m-l; //在下面会贴出来 } } for(int i=x;i<y;i++) { a[i]=t[i]; } //从这里往上 }}int main (){ int n; cin>>n; for(int i=1;i<=n;i++) { cin>>a[i]; } mid_sort(1,n+1);/*因为归并排序 是排序[1,n)的数,所以我们要把n+1*/ cout<<cnt; return 0;}
while(l<m||r<y) { if(r>=y||(l<m && a[l]<=a[r])) t[i++]=a[l++]; else{ t[i++]=a[r++]; cnt+=m-l; } } for(int i=x;i<y;i++) { a[i]=t[i]; }
首先讲一下归并排序 会的直接跳过就好
先看其中的判断
if(r>=y||(l<m && a[l]<=a[r]))
如果我们只是单纯的去比较当前的左区间和右区间 当前的数的大小从而决定将哪个数放入临时数组 这样是有一个bug 的 就是如果有一个区间空了怎么办
所以 我们在此分为三种情况
其中第一种情况是:如果右区间为空 此时还在while循环里 也就是说 左区间一定非空 所以此时我们只需要将左区间剩下的数复制进临时数组即可。
另一种情况是:如果右区间不是空的 此时如果左区间也是非空的(这就是l < m的意义) 且 a[l]<=a[r] 我们就复制左区间的数。
剩下的情况就是复制右区间的条件了。
for(int i=x;i<y;i++) { a[i]=t[i]; }
这是将临时数组中的数复制到原数组的过程
end
接下来是逆序对的求法
很简单只需要加一条语句就行
在刚刚的代码已经贴出来了:
cnt+=m-l;
cnt 是逆序对的总数
为什么这样做:
当我们从右区间拿出来一个数a之后 此时就代表着左区间剩下的数一定比当前从右区间拿出的数大 所以此时左区间剩下的数就是有关a的逆序对数
end
阅读全文
0 0
- 求逆序对 (用归并) nlogn
- 归并排序求逆序对 O(nlogn)
- 求逆序对(复杂度为nlogn)
- 归并求逆序对
- 归并求逆序对
- 归并方法求逆序对(洛谷1908逆序对)
- 用归并排序求逆序对
- 求逆序数对(归并排序)
- 求逆序对(归并排序)
- 归并排序求逆序对
- poj1007 归并求逆序对
- 归并排序求逆序对
- 归并排序求逆序对~~~
- 归并求逆序对【模板】
- 归并排序求逆序对
- 归并排序求逆序对
- 归并排序求逆序对
- 归并排序求逆序对
- 机器算法实战中logistcal回归与SKlearn库算法对比
- 5.0 FIR数字滤波器引论
- 基于Xposed修改微信运动步数
- 实战Java高并发程序设计之ReadWriteLock
- Intent的学习小记
- 求逆序对 (用归并) nlogn
- mfc重定向到控制台
- mysql5.7.18安装 密码恢复、
- 接前-递归遍历二叉树
- 基于Xposed修改微信运动步数
- Spring 集成 Axis2 1.7.5
- 图像显著性区域提取[2]-特征提取
- 对象的内存布局和访问方式
- Qt各版本官方下载地址