1. 程式人生 > >POJ 2299 -- Ultra-QuickSort

POJ 2299 -- Ultra-QuickSort

亂序序列 blog app sea 次數 min 復雜 water 圖片

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

Waterloo local 2005.02.05 題意: 輸入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)

樹狀數組詳細講解,不會算法也能看懂哦~

記錄一下,以後再學習……

POJ 2299 -- Ultra-QuickSort