NYOJ 117 求逆序数 (归并排序)

地址:http://acm.nyist.net/JudgeOnline/problem.php?pid=117

思路:归并排序,表示不太懂。。。。

算法分析:这个题的算法是利用归并排序的 merge() 函数,在处理在处理两段时,恰好要比较大小,顺便把逆数也求出来 故时间复杂度o(nlogn);

 1 #include<stdio.h>
 2 #include<stdlib.h>
 3 #define N 1000010
 4 long long ans;
 5 int a[N];
 6 void merge(int s1,int e1,int s2,int e2)
 7 {
 8     int p1,p2,p;
 9     int* temp = new int[e2-s1+5];  //归并为有序的temp ,此处定义temp 
10     p=0;p1=s1;p2=s2;
11     while(p1<=e1&&p2<=e2)   //将s1到e1和s2到e2合并到temp 
12     {
13         if(a[p1]<=a[p2])
14         {
15             temp[p++]=a[p1++];
16             continue;
17         }
18         else 
19         {
20             temp[p++]=a[p2++];
21             ans+=e1-p1+1;   //关键所在
22             continue;
23         }
24     }
25     while(p1<=e1) temp[p++]=a[p1++];  //将剩余的复制到temp 
26     while(p2<=e2) temp[p++]=a[p2++];
27     int i;
28     for(i=s1;i<=e2;i++) a[i]=temp[i-s1];
29     delete temp;
30 }
31 
32 void merge_sort(int s,int e)
33 {
34     int m;
35     if(s<e)
36     {
37         m=(s+e)/2;
38         merge_sort(s,m);
39         merge_sort(m+1,e);
40         merge(s,m,m+1,e);
41     }
42 }
43 
44 int main()
45 {
46     int test;
47     scanf("%d",&test);
48     while(test--)
49     {
50         int n,i;
51         ans=0;
52         scanf("%d",&n);
53         for(i=0;i<n;i++)
54             scanf("%d",&a[i]);
55         merge_sort(0,n-1);
56         printf("%lld\n",ans);
57     }
58 }

用归并排序求逆序数。归并排序中适当的位置加上cnt+=n1-i,就可以了。

 

 

posted on 2012-08-17 09:39  mycapple  阅读(1118)  评论(0编辑  收藏  举报

导航