POJ 2299 -- Ultra-QuickSort

Ultra-QuickSort
Time Limit: 7000MS   Memory Limit: 65536K
Total Submissions: 65986   Accepted: 24686

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

Source

 
题意:
输入n个数,问至少经过多少次两两交换,可以得到一个升序序列
n < 500,000 -- the length of the input sequence
 0 ≤ a[i] ≤ 999,999,999
 
解题:
1)利用归并排序求逆序数
一个乱序序列的 逆序数 = 在只允许相邻两个元素交换的条件下,得到有序序列的交换次数

注意保存逆序数的变量t,必须要用__int64定义,int一定会溢出的,而long long 在现在的VC编译器已经无法编译了。

注意__int64类型的输出必须使用指定的c格式输出,printf(“%I64d”,t);

cout是无法输出__int64类型的

序列数组s[]用int就足够了,每个元素都是小于10E而已

 1 #include<iostream>
 2 #include<cstdio>
 3 using namespace std;
 4 int const maxa = 500005;
 5 __int64 ans;//逆序数
 6 int a[maxa];//存储n个数
 7 
 8 void Merge(int left,int mid,int right)
 9 {
10     int len_l = mid-left+1;
11     int len_r = right-mid;
12     int* aLeft = new int[len_l+2];
13     int* aRight = new int[len_r+2];
14     for(int i=1;i<=len_l;i++)
15         aLeft[i] = a[left+i-1];
16     aLeft[len_l+1] = 10000000000;//设置一个很大的上界防止溢出
17     for(int i=1;i<=len_r;i++)
18         aRight[i] = a[i+mid];
19     aRight[len_r+1] = 10000000000;//设置一个很大的上界防止溢出
20     int m=1,n=1;
21     for(int i=left;i<=right;i++)
22     {
23         if(aLeft[m] <= aRight[n])
24             {
25                 a[i] = aLeft[m];m++;
26             }
27         else{
28             ans+=len_l-m+1;
29             a[i] = aRight[n];n++;
30         }
31     }
32     delete aLeft;
33     delete aRight;
34     return;
35 
36 }
37 
38 void mergeSort(int left,int right)
39 {
40     if(left<right)
41     {
42         int mid = (left + right)/2;
43         mergeSort(left,mid);
44         mergeSort(mid+1,right);
45         Merge(left,mid,right);
46     }
47     return;
48 }
49 
50 int main()
51 {
52     int n;
53     while(cin>>n && n!=0)
54     {
55         for(int i=1;i<=n;i++)
56             cin>>a[i];
57         ans = 0;
58         mergeSort(1,n);
59         printf("%I64d\n",ans);
60     }
61 
62     return 0;
63 }

为什么要使用归并呢?这是因为输入的数据量可能会达到50W

下图的测试是使用插入排序,不出意外的超时了

所以使用归并排序,时间复杂度为O(nlogn)

只有堆排序归并排序时间复杂度可以控制在O(nlogn),因为他们都用用空间换时间,其他的排序算法在最坏的情况下,时间复杂度均为O(n^2)

 

2)树状数组

树状数组例题(poj2299)

树状数组详细讲解,不会算法也能看懂哦~

记录一下,以后再学习……

 

posted @ 2018-02-09 21:15  卉卉卉大爷  阅读(145)  评论(0编辑  收藏  举报