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.
Ultra-QuickSort produces the output
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
题意:将一个序列从小到大排序,如果只能交换相邻的数,最少需要交换多少次
思路:和冒泡排序一样,一个数需要交换的次数就是它的逆序对数,所以就是求总的逆序对的个数
求逆序对可以用两种方法
①归并排序:
1 #include<cstdio> 2 #include<iostream> 3 using namespace std; 4 5 int n; 6 const int maxn = 5e5+5; 7 int num[maxn]; 8 typedef long long ll; 9 10 ll Mersort(int l,int r) 11 { 12 int mid = (l+r)/2; 13 int i=l,j=mid+1; 14 int b[r-l+5]; 15 int k=1; 16 ll ans = 0; 17 while(i <= mid && j <= r) 18 { 19 if(num[i] <= num[j]) 20 b[k++] = num[i++]; 21 else 22 b[k++] = num[j++],ans+=mid-i+1; 23 } 24 while(i <= mid) 25 { 26 b[k++] = num[i++]; 27 } 28 while(j <= r) 29 { 30 b[k++] = num[j++]; 31 } 32 for(int i=l; i<=r; i++) 33 { 34 num[i] = b[i-l+1]; 35 } 36 return ans; 37 } 38 39 int Merge(int l,int r,ll &ans) 40 { 41 int mid = (l+r)/2; 42 if(l == r) 43 return 0; 44 Merge(l,mid,ans); 45 Merge(mid+1,r,ans); 46 ans += Mersort(l,r); 47 } 48 int main() 49 { 50 while(~scanf("%d",&n) && n) 51 { 52 for(int i=1; i<=n; i++) 53 scanf("%d",&num[i]); 54 ll ans = 0; 55 Merge(1,n,ans); 56 printf("%lld ",ans); 57 } 58 }
②树状数组:(要注意离散,离散可以二分,也可以map)
1 #include<cstdio> 2 #include<iostream> 3 #include<algorithm> 4 #include<string.h> 5 using namespace std; 6 7 const int maxn = 5e5+5; 8 int n; 9 int tree[maxn]; 10 typedef long long ll; 11 12 int lowbit(int x) 13 { 14 return x&(-x); 15 } 16 17 void add(int x) 18 { 19 for(int i=x;i<=n;i+=lowbit(i)) 20 { 21 tree[i]++; 22 } 23 } 24 25 int Query(int x) 26 { 27 int ans = 0; 28 for(int i=x;i>0;i-=lowbit(i)) 29 { 30 ans+=tree[i]; 31 } 32 return ans; 33 } 34 int query(int x,int n,int *b) 35 { 36 return lower_bound(b+1,b+1+n,x) - b; 37 } 38 int main() 39 { 40 while(~scanf("%d",&n) && n) 41 { 42 memset(tree,0,sizeof(tree)); 43 int a[n+1],b[n+1]; 44 for(int i=1;i<=n;i++)scanf("%d",&a[i]),b[i] = a[i]; 45 sort(b+1,b+1+n); 46 int len = unique(b+1,b+1+n)-b-1; 47 ll ans = 0; 48 for(int i=1;i<=n;i++) 49 { 50 int pos = query(a[i],len,b); 51 add(pos); 52 ans += pos - 1 - Query(pos-1); 53 } 54 printf("%lld ",ans); 55 } 56 }