求排序的数最少的交换次数。只能相邻的交换。
归并排序算法:
#include<stdio.h> #include<limits.h> const int MAXN = 500000 + 10; const int INF = INT_MAX; long long tot;//tot为逆序数总数。 int arr[MAXN]; //将b数组中的元素复制到a数组中。 void CopyArray(int a[], int b[], int len, int left) { for(int i = 0; i < len; i++) { a[left++] = b[i]; } } //归并排序,合并两个子序列中的元素。 void Merge(int a[], int left, int right) { int begin1, begin2, mid, k=0, len; begin1 = left; mid = (left+right)/2; begin2 = mid+1; len = right-left+1; int *b = new int[len]; while(begin1 <= mid && begin2 <= right) { if(a[begin1] < a[begin2]) { b[k++] = a[begin1++]; } else { b[k++] = a[begin2++]; tot += (mid - begin1 + 1); //当后面的有序序列中的元素小与前面的有序序列的元素, //那么总的逆序数要加上前面有序序列中剩余的元素的个数, //因为这些是有序的,所以加上的那些数每个都比后面的序列中参与比较的元素大。 } } while(begin1 <= mid) { b[k++] = a[begin1++]; } while(begin2 <= right) { b[k++] = a[begin2++]; } CopyArray(a, b, len, left); delete b; } //归并排序。 void Msort(int a[], int s, int t) { int m; if( s<t ) { m = ( s+t ) /2; Msort(a, s, m); Msort(a, m+1, t); Merge(a, s, t); } } int main() { int n; while(scanf("%d", &n), n) { tot = 0; for(int i = 0; i < n; i++) { scanf("%d", &arr[i]); } Msort(arr, 0, n-1); printf("%lld\n", tot); } return 0; }
树状数组:
#include<iostream> #include<algorithm> #define M 500001 using namespace std; int c[M],aa[M],n; //aa数组为排序后重新编号用 struct digit { int num,id; } a[M]; //num为数的大小 bool cmp(digit a,digit b) { return a.num<b.num; } int lowbit(int t) { return t&(t^(t-1)); } int sum(int t) { int total=0; while(t>0) { total+=c[t]; t-=lowbit(t); } return total; } void update(int t,int key) { while(t<=n) { c[t]+=key; t+=lowbit(t); } } int main() { int i,j; long long ans; while(scanf("%d",&n),n) { memset(c,0,sizeof(c)); ans=0; for(i=1; i<=n; i++) { scanf("%d",&a[i].num); a[i].id=i; } sort(a+1,a+n+1,cmp); aa[a[1].id]=1; //最小的数编号为1 for(i=2; i<=n; ++i) { if(a[a[i].id].num!=a[a[i-1].id].num) //如果前后两个数不等,则编号为下标 aa[a[i].id]=i; else aa[a[i].id]=aa[a[i-1].id]; //否则编号与前一个相同 } //for(i=1;i<=n;i++) printf("%d ",aa[i]); for(i=1; i<=n; ++i) { update(aa[i],1); ans+=(sum(n)-sum(aa[i])); //每次累加该数前边比它大的数的个数 } printf("%lld\n",ans); } }
Ultra-QuickSort
Time Limit: 7000MS Memory Limit: 65536K
Total Submissions: 27681 Accepted: 9924
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