POJ 2299 Ultra-QuickSort

来源:互联网 发布:淘宝天猫8折代购原理 编辑:程序博客网 时间:2024/06/05 22:30

题目:

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

59105431230

Sample Output

60

题意很好理解,输入一个数列,输出它的逆序数。

我的原始代码(超时):

#include<iostream>using namespace std;int n;int c[500005];int num[500005];int sum(int i){int s = 0;while (i){s += c[i];i -= (i&(-i));}return s;}void add(int i, int x){while (i <= n){c[i] += x;i += (i&(-i));}}int findmax(){int max = 1;for (int j = 2; j <= n; j++)if (num[max] < num[j])max = j;return max;}int main(){ios_base::sync_with_stdio(false);long long s;while (cin >> n){if (n == 0)break;for (int i = 1; i <= n; i++){cin >> num[i];c[i] = 0;}s = 0;for (int i = 1; i <= n; i++){int j = findmax();num[j] = -1;s += sum(j);add(j, 1);}cout << s << endl;}return 0;}

很明显它的时间是n*n,所以超时了。

但是好在思路差的不是很多,稍微改了下就对了。

代码:

#include<iostream>#include<algorithm>using namespace std;struct node{int num;int index;};int n;int c[500005];node nod[500005];bool cmp(node a, node b){return a.num > b.num;}int sum(int i){int s = 0;while (i){s += c[i];i -= (i&(-i));}return s;}void add(int i, int x){while (i <= n){c[i] += x;i += (i&(-i));}}int main(){ios_base::sync_with_stdio(false);long long s;while (cin >> n){if (n == 0)break;for (int i = 1; i <= n; i++){cin >> nod[i].num;nod[i].index = i;c[i] = 0;}s = 0;sort(nod + 1, nod + 1 + n, cmp);for (int i = 1; i <= n; i++){int j = nod[i].index;s += sum(j);add(j, 1);}cout << s << endl;}return 0;}

这个虽然过了,但是很慢,我猜想手写快速排序或者归并排序应该会比较快。

普通的归并排序,只需要加一句sum += mid - i + 1;就可以变成边排序边统计逆序数。

代码:

#include<iostream>using namespace std;int n;long long sum;int num[500005];int copynum[500005];void merge(int low, int high){int mid = (low + high) / 2;int i = low, j = mid + 1, k = low;while (i <= mid && j <= high){if (num[i] < num[j])copynum[k++] = num[i++];else{copynum[k++] = num[j++];sum += mid - i + 1;}}while (i <= mid)copynum[k++] = num[i++];while (j <= high)copynum[k++] = num[j++];for (int i = low; i <= high; i++)num[i] = copynum[i];}void sort(int low, int high){if (low == high)return;int mid = (low + high) / 2;sort(low, mid);sort(mid + 1, high);merge(low, high);}int main(){ios_base::sync_with_stdio(false);while (cin >> n){if (n == 0)break;for (int i = 1; i <= n; i++)cin >> num[i];sum = 0;sort(1, n);cout << sum << endl;}return 0;}

2 0
原创粉丝点击