算法竞赛入门经典:第八章 高效算法设计 8.3归并排序应用之逆序对数
2015-08-18 09:39
369 查看
/* 逆序对数: 给出一列数a1,a2,...,an,求它的逆序对数,即有多少个有序对(i,j),使得i<j但ai>aj。n可以高达10^6 思路: 分解成前后两个序列,统计后序列中每个元素与前面中每个元素的逆序对数,是一个叉乘 书析: 采用O(n^2)枚举超时,因为n很大。 划分:将序列等分 递归求解:统计i和j均在左边或者均在右边的逆序对个数 合并:统计i在左边,但j在右边的个数 划分与递归都好办, 合并:如何求出i在左边,j在右边的逆序对数目。 技巧:分类,按照j的不同把这些“跨越两边”的逆序对进行分类,对于右边的每个j,统计左边比它大的元素个数f(j),所有f(j)之和便是答案。 合并操作是从小到大进行的,当右边的A[j]复制到T中时,左边没来得及复制到T的那些数就是左边所有比A[j]大的个数,及m-p,左边所剩元素在[p,m)中 因此只需要在 else { iTempArr[i++] = iArr[m]; iCnt += mid - l;//只需要加上这一句即可 } 输入: 8 1 9 6 3 4 7 9 0 输出: 0 1 3 4 6 7 9 9 13 (1+5+3+1+1+1+1=13) */ /* 关键: 1 采用O(n^2)枚举超时,因为n很大。 递归求解:统计i和j均在左边或者均在右边的逆序对个数 合并:统计i在左边,但j在右边的个数 2 技巧:分类,按照j的不同把这些“跨越两边”的逆序对进行分类,对于右边的每个j,统计左边比它大的元素个数f(j),所有f(j)之和便是答案。 3 合并操作是从小到大进行的,当右边的A[j]复制到T中时,左边没来得及复制到T的那些数就是左边所有比A[j]大的个数,及m-p,左边所剩元素在[p,m)中 因此只需要在 else { iTempArr[i++] = iArr[m]; iCnt += mid - l;//只需要加上这一句即可 } 4 if(m >= high || (l < mid && iArr[l] <= iArr[m]))//=与号不能漏 5 快速排序: 划分:数组重排后分成两部分,左边均<=右边 递归求解:把左右两部分分别排序 合并:不用合并,数组已经完全有序 */ #include <stdio.h> #define MAXSIZE 1024 int iCnt; void mergeSort(int* iArr,int low,int high,int* iTempArr) { if(1 < high - low) { int mid = low + (high - low) / 2 ; int l = low,m = mid,i = low; mergeSort(iArr,low,mid,iTempArr); mergeSort(iArr,mid,high,iTempArr); while(l < mid || m < high) { //if(m >= high || (l < mid && iArr[l] < iArr[m])) if(m >= high || (l < mid && iArr[l] <= iArr[m]))//=与号不能漏 { iTempArr[i++] = iArr[l++]; } else { iTempArr[i++] = iArr[m++]; iCnt += mid - l; } } for(int j = low ; j < high ; j++) { iArr[j] = iTempArr[j]; } } } void print(int* iArr,int n) { for(int i = 0 ; i < n; i++) { if(i) { printf(" %d",iArr[i]); } else { printf("%d",iArr[i]); } } printf("\n"); } void process() { int n; while(EOF != scanf("%d",&n)) { iCnt = 0; int iArr[MAXSIZE]; int iTempArr[MAXSIZE]; for(int i = 0; i < n ; i++) { scanf("%d",&iArr[i]); } mergeSort(iArr,0,n,iTempArr); print(iArr,n); printf("%d\n",iCnt); } } int main(int argc,char* argv[]) { process(); getchar(); return 0; }
相关文章推荐
- linux基础知识1
- ORA-01461: 仅能绑定要插入 LONG 列的 LONG 值
- 欢迎使用CSDN-markdown编辑器
- 淘宝取代分布式事务的方案
- 算法竞赛入门经典:第八章 高效算法设计 8.2归并排序
- nginx部署
- 协方差矩阵
- framework中编译anroid工程并在模拟器上运行
- 6、MPU6050例程
- eclipse + Felix 开发环境搭建 bundle 开发与调试
- 【LeetCode-面试算法经典-Java实现】【05-Longest Palindromic Substring(最大回文字符串)】
- ip,tcp,udp,rudp包头
- [转]让程序员跳槽的非钱原因
- 组合数相关的一些问题
- linux下C语言编译为汇编代码
- linux进程间通讯的几种方式的特点和优缺点
- 算法竞赛入门经典:第八章 高效算法设计 8.1动态规划之最大连续和
- CSS中绝对定位解释
- JS中的prototype
- 树莓派 rtl8188eu 芯片wifi驱动