POJ2299 Ultra-QuickSort

题目链接:https://vjudge.net/problem/POJ-2299

题目大意:

  求数列中逆序对的个数。

知识点:  归并排序

解题思路:

  对于数列中的每一个逆序对,它们之间早晚都需要一次邻位变换,因此答案即为数列中逆序对的个数。

  我们用归并排序求逆序对个数:对于左右两个已经排好序的子区间,在合并之前先用一种\(O(n)\)的方式计算出母区间中逆序对的个数,具体方式见代码。

AC代码:

 1 #include <cstdio>
 2 using namespace std;
 3 typedef long long ll;
 4 const int maxn = 500000+5;
 5 ll a[maxn],temp[maxn];
 6 ll ans;
 7 void MergeSort(int l,int r){
 8     if(l==r)    return;
 9     int m=(l+r)>>1;
10     MergeSort(l,m); MergeSort(m+1,r);
11     for(int i=m,j=r;i>=l&&j>=m+1;){//计算逆序对个数
12         if(a[i]>a[j]){
13             ans+=(j-m);
14             i--;
15         }
16         else    j--;
17     }
18     for(int i=l,j=m+1,ind=0;i<=m||j<=r;ind++){
19         if(i>m) temp[ind]=a[j++];
20         else if(j>r)    temp[ind]=a[i++];
21         else if(a[i]<a[j])   temp[ind]=a[i++];
22         else if(a[j]<a[i])   temp[ind]=a[j++];
23     }
24     for(int i=l,j=0;i<=r;i++,j++) a[i]=temp[j];
25 }
26 int main(){
27     int n;
28     while(scanf("%d",&n)==1&&n){
29         ans=0;
30         for(int i=1;i<=n;i++)   scanf("%lld",&a[i]);
31         MergeSort(1,n);
32         printf("%lld\n",ans);
33     }
34     return 0;
35 }

 

posted @ 2018-02-14 13:28  Blogggggg  阅读(132)  评论(0编辑  收藏  举报