poj 2299 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

求逆序对数,具体思路是,在归并的过程中计算每个小区间的逆序对数,进而计算出大区间的逆序对数.
归并过程为:比较a[i]和a[j]的大小,若a[i]≤a[j],则将第一个有序表中的元素a[i]复制到r[k]中,并令i和k分别加上1;否则将第二个有序表中的元素a[j]复制到r[k]中,并令j和k分别加上1,如此循环下去,直到其中一个有序表取完,然后再将另一个有序表中剩余的元素复制到r中从下标k到下标t的单元。归并排序的算法我们通常用递归实现,先把待排序区间[s,t]以中点二分,接着把左边子区间排序,再把右边子区间排序,最后把左区间和右区间用一次归并操作合并成有序的区间[s,t]。

归并实现:直接套模板

 1 #include <iostream>
 2 #include <cstdio>
 3 using namespace std;
 4 int n,a[500005],b[500005];
 5 long long count;
 6 void Merge(int *a,int left,int mid,int right)
 7 {
 8     int i=left,j=mid+1,k=left;
 9     while(i!=mid+1&&j!=right+1)
10     {
11         if(a[i]>a[j])
12         {
13             //count+=j-k;
14             b[k++]=a[j++];
15             count+=mid-i+1;
16         }
17         else
18         {
19             b[k++]=a[i++];
20         }
21     }
22     while(i!=mid+1)
23         b[k++]=a[i++];
24     while(j!=right+1)
25         b[k++]=a[j++];
26     for(i=left; i<=right; i++)
27         a[i]=b[i];
28 }
29 void Merge_sort(int *a,int left,int right)
30 {
31     if(left==right)
32         return ;
33     int mid=(left+right)>>1;
34     Merge_sort(a,left,mid);
35     Merge_sort(a,mid+1,right);
36     Merge(a,left,mid,right);
37 }
38 int main()
39 {
40     while(scanf("%d",&n),n)
41     {
42         count=0;
43         for(int i=0; i<n; i++)
44             scanf("%d",&a[i]);
45         Merge_sort(a,0,n-1);
46         printf("%lld
",count);
47     }
48     return 0;
49 }
View Code
原文地址:https://www.cnblogs.com/cxbky/p/4871794.html