51Nod-1019-逆序数
来源:互联网 发布:直播软件tv版 编辑:程序博客网 时间:2024/06/10 21:18
在一个排列中,如果一对数的前后位置与大小顺序相反,即前面的数大于后面的数,那么它们就称为一个逆序。一个排列中逆序的总数就称为这个排列的逆序数。
如2 4 3 1中,2 1,4 3,4 1,3 1是逆序,逆序数是4。给出一个整数序列,求该序列的逆序数。
Input
第1行:N,N为序列的长度(n <= 50000)
第2 - N + 1行:序列中的元素(0 <= A[i] <= 10^9)
Output
输出逆序数
Input示例
4
2
4
3
1
Output示例
4
对于这道题,直接上来的思路就是进行选择对比(类似于选择排序,只不过忽略排序过程),但是只过了七成的数据,所以是不怎么好的,于是乎,了解到,可以用归并排序来做这道题,说到归并排序,最常用的就是用递归来实现,但是其中涉及到一个不断开数组的过程,很有可能会导致题爆掉,所以也是存在很大问题的,所以,想要实现这道题,初步判定需要归并排序,但是要使用非递归实现归并排序,也就是迭代实现。先上递归实现的代码(C):
#include <stdio.h>#define _MAX 50001long ans = 0;//将有序的A[first..mid]和A[mid + 1..last]归并为有序的B[first..last]void Merge(long *A, long *B, int first, int mid, int last){ int i = first, j = mid + 1; int cur = first; while (i <= mid && j <= last) { if (A[i] <= A[j]) { B[cur++] = A[i++]; } else { B[cur++] = A[j++]; ans += mid - i + 1; //核心代码,逆序数增加 } } while (i <= mid) { B[cur++] = A[i++]; } while (j <= last) { B[cur++] = A[j++]; }}//将A[first..last]归并排序为B[first..last]void MSort(long *A, long *B, int first, int last){ int mid; long BT[_MAX]; //这里存在问题,当数据大时,递归层数多,容易爆掉。 if (first == last) { B[first] = A[first]; } else { mid = (first + last) / 2; MSort(A, BT, first, mid); MSort(A, BT, mid + 1, last); Merge(BT, B, first, mid, last); } return ;}int main(int argc, const char * argv[]){ int N, i = 1; long A[_MAX]; scanf("%d", &N); for (; i <= N; i++) { scanf("%ld", &A[i]); } MSort(A, A, 1, N); printf("%ld\n", ans); return 0;}
这个代码只过了七成的测试数据,不是完美的解题代码,所以接下来要给出真正可行的代码,如下(C):
#include <stdio.h>#include <stdlib.h>#define _MAX 50001long ans = 0;//将有序的A[first..mid]和A[mid + 1..last]归并为有序的B[first..last]void Merge(long *A, long *B, int first, int mid, int last){ int i = first, j = mid + 1; int cur = first; while (i <= mid && j <= last) { if (A[i] <= A[j]) { B[cur++] = A[i++]; } else { B[cur++] = A[j++]; ans += mid - i + 1; //核心代码,逆序数增加 } } while (i <= mid) { B[cur++] = A[i++]; } while (j <= last) { B[cur++] = A[j++]; }}//将A中相邻长度为s的子序列两两归并到B中void MergePass(long *A, long *B, int k, int N){ int i = 1, j; while (i <= N - 2 * k + 1) { Merge(A, B, i, i + k - 1, i + 2 * k - 1); i = i + 2 * k; } if (i < N - k + 1) { Merge(A, B, i, i + k - 1, N); } else { for (j = i; j <= N; j++) { B[j] = A[j]; } }}void MSort(long *A, int N){ long *B = (long *)malloc(sizeof(long) * N); int k = 1; while (k < N) { MergePass(A, B, k, N); k *= 2; MergePass(B, A, k, N); k *= 2; } return ;}int main(int argc, const char * argv[]){ int N, i = 1; long A[_MAX]; scanf("%d", &N); for (; i <= N; i++) { scanf("%ld", &A[i]); } MSort(A, N); printf("%ld\n", ans); return 0;}
理论上这种写法是可以AC的,但是不知道为啥,在三组测试数据中出现了运行时错误,一下子整个人都不自在了,25组测试数据,大的过去了,小的也过去了,偏偏是这中不溜的三组数据出现了问题,自己本地测试数据,结果均正确,搞得我不知所以了……
最后经过代码优化,只好写成这样才算是过去了-_-#
#include <stdio.h>#define _MAX 50001long ans = 0;//将有序的A[first..mid]和A[mid + 1..last]归并为有序的B[first..last]void Merge(long *A, long *B, int first, int mid, int last){ int i = first, j = mid + 1; int cur = first; while (i <= mid && j <= last) { if (A[i] <= A[j]) { B[cur++] = A[i++]; } else { B[cur++] = A[j++]; ans += mid - i + 1; //核心代码,逆序数增加 } } while (i <= mid) { B[cur++] = A[i++]; } while (j <= last) { B[cur++] = A[j++]; }}//将A[first..last]归并排序为B[first..last]void MSort(long *A, long *B, int first, int last){ int mid; if (first < last) { mid = (first + last) / 2; MSort(B, A, first, mid); MSort(B, A, mid + 1, last); Merge(A, B, first, mid, last); } return ;}int main(int argc, const char * argv[]){ int N, i = 1; long A[_MAX]; long B[_MAX]; scanf("%d", &N); for (; i <= N; i++) { scanf("%ld", &A[i]); B[i] = A[i]; } MSort(A, B, 1, N); printf("%ld\n", ans); return 0;}
累死宝宝了!!!OVER!!!
1 0
- 51Nod-1019-逆序数
- 51nod 1019 逆序数
- 51nod 1019 逆序数
- [51nod]1019 逆序数
- 51nod 1019 逆序数
- 51nod 1019 逆序数
- 51nod 1019 逆序数
- 51nod 1019 逆序数
- 51nod 1019逆序数
- 51Nod--1019 逆序数
- 51Nod 1019 逆序数
- 51Nod-1019-逆序数
- 51Nod 1019 逆序数
- 51nod 1019 逆序数
- 51Nod 1019 逆序数
- 51Nod 逆序数
- 51nod逆序数
- 逆序数 51Nod
- Iocomp控件教程之数码管控件汇总
- 文章标题
- Android学习笔记(38):Handler消息传递处理机制
- 权限设计
- C++字符串完全指南
- 51Nod-1019-逆序数
- cannot open file "uafxcwd.lib"
- Android学习笔记(39):异步任务AsyncTask
- MBR总结
- Android应用的界面编程:ProgressBar及其子类[SeekBar、RatingBar]
- 解决 MySQL 5.7 中 Your password does not satisfy the current policy requirements. 问题
- progressBar与seekBar区别
- oracle基本常识
- java代理理解