Ultra-QuickSort
Description
In this problem, you have to analyze a particular sorting algorithm. The algorithm processes a sequence of n distinct integers by swapping two adjacent sequence elements until the sequence is sorted in ascending order. For the input sequence
9 1 0 5 4 ,
Ultra-QuickSort produces the output
0 1 4 5 9 .
Your task is to determine how many swap operations Ultra-QuickSort needs to perform in order to sort a given input sequence.
Input
The input contains several test cases. Every test case begins with a line that contains a single integer n < 500,000 -- the length of the input sequence. Each of the the following n lines contains a single integer 0 ≤ a[i] ≤ 999,999,999, the i-th input sequence element. Input is terminated by a sequence of length n = 0. This sequence must not be processed.
Output
For every input sequence, your program prints a single line containing an integer number op, the minimum number of swap operations necessary to sort the given input sequence.
Sample Input
5 9 1 0 5 4 3 1 2 3 0
Sample Output
6 0
题目大概意思:实质上就是求一个数列的逆序数。而其中我们可以运用归并排序的过程来求解,也就是将问题转化为将一个无序数列归并排序了。归并排序的思想,就是将数列不断的分割成小得足够能求解的子数列,求解后再把子答案合并成原始问题的答案。下面我通过代码来一一讲解其中的注意点。
#include <iostream> using namespace std; int a[500050]; int b[500050]; long long cnt;//注意次数可能爆掉 void merge(int *a, int first, int mid, int end) { int i, x; int y = mid+1; i = first; x = first; while((x<=mid) && (y<=end))//执行的条件是两部分都不能为空 { if (a[x]<=a[y]) { b[i++] = a[x++];//先赋值再下标下移 } else { cnt += mid-x+1;//每次左边剩下的数意味着存在左边比右边大的数,也就是存在逆序,再计数把所有左边数加起来就是整个数列的逆序数 b[i++] = a[y++]; } }
//这一部分要注意,上面部分执行的条件是两部分都不能为空,那么要是有一个空了,另一个必定没空,下面的代码就是处理这个问题。一句话,就是把另一个没空的部 分全部接到已排好序的后面就行了。刚开始我犯糊涂地疑问,为什么直接复制就可以了,万一剩下的部分是无序的呢?但是我忽略了这已经是在合并了,是建立在子问 题已经解决的基础上的,所以剩下的部分必定是有序的啦。 while (x <= mid) { b[i++] = a[x++]; } while (y <= end) { b[i++] = a[y++]; } while (first <= end) { a[first] = b[first]; first++; } } void merge_sort (int *a,int first, int end) { if (first < end) { int mid = first+ (end-first)/2; merge_sort(a,first,mid);//将问题分解,调用递归 merge_sort(a,mid+1,end); merge(a,first,mid,end);//合并的过程 } } int main () { int n; while (cin >> n && n) { cnt = 0; for (int i = 0; i< n;i++) { cin >> a[i]; } merge_sort(a,0,n-1); cout << cnt <<endl; } return 0; }
编者有话:每次自己写题没有思路的时候,上网找题解啊,但是很多人总是贴个代码就完事了,最讨厌这样了,个人觉得要么把思路讲出来,越详细越好,初学者真的挺吃力的,宁可要详细的思路,也不要没有一点注释的代码,我是这样想的。当然有思路,代码有详细注释,特别是一些难理解的地方就更好了。