Ultra-QuickSort(归并排序)

http://poj.org/problem?id=2299

此题即为归并排序求逆序数。

 1 #include<stdio.h>
 2 #include<string.h>
 3 const int N=500002;
 4 int a[N],temp[N];
 5 long long  ans;
 6 void merge_arr(int first,int mid,int last)//合并区间
 7 {
 8     int k = 0;
 9     int i = first,n = mid;
10     int j = mid+1,m = last;
11     while(i <= n && j <= m)
12     {
13         if (a[i] <= a[j])
14             temp[k++] = a[i++];
15         else
16         {
17             temp[k++] = a[j++];
18             ans += (mid-i+1);//计算逆序数
19         }
20     }
21     while(i <= n)
22         temp[k++] = a[i++];
23     while(j <= m)
24         temp[k++] = a[j++];
25     for (i = 0; i < k; i ++)
26         a[first+i] = temp[i];//将有序的temp[]赋给原数组
27 }
28 void mergesort(int first,int last)//归并排序
29 {
30     if (first < last)
31     {
32         int mid = (first+last)/2;
33         mergesort(first,mid);
34         mergesort(mid+1,last);
35         merge_arr(first,mid,last);
36     }
37 }
38 int main()
39 {
40     int n;
41     while(~scanf("%d",&n)&&n)
42     {
43         ans = 0;
44         for (int i = 0; i < n; i ++)
45         {
46             scanf("%d",&a[i]);
47         }
48         mergesort(0,n-1);
49         printf("%lld
",ans);
50     }
51     return 0;
52 }
View Code

同类型的题:

http://poj.org/problem?id=1804 

Brainman

题意:给出n个数,只能相邻的两个数交换,问最少交换多少次才能使这n个数递增排列。

思路:求出该序列的逆序数即为最少交换的次数。

法一:直接暴力o(n^2)

 1 #include <stdio.h>
 2 #include <algorithm>
 3 #include <string.h>
 4 using namespace std;
 5 const int N=1005;
 6 
 7 int a[N];
 8 
 9 int main()
10 {
11     int t,o = 0;
12     scanf("%d",&t);
13     while(t--)
14     {
15         o++;
16         int n;
17         scanf("%d",&n);
18         for (int i = 0; i < n; i++)
19             scanf("%d",&a[i]);
20 
21         int cnt = 0;
22         for (int i = 0; i < n; i++)
23         {
24             for (int j = i+1; j < n; j++)
25             {
26                 if (a[i] > a[j])
27                     cnt++;
28             }
29 
30         }
31         printf("Scenario #%d:
%d

",o,cnt);
32     }
33     return 0;
34 }
View Code

法二:归并排序 o(nlogn)

 1 #include <stdio.h>
 2 #include <string.h>
 3 const int N=1002;
 4 const int INF = 1<<28;
 5 long long ans = 0;
 6 void Merge(int *a,int s,int mid,int t)
 7 {
 8     int lenl= mid-s+1;
 9     int lenr = t-mid;
10     int *b = new int[lenl+2];
11     int *c = new int[lenr+2];
12     for (int i = 1; i <= lenl; i++)
13         b[i] = a[s+i-1];
14     b[lenl+1] = INF;
15     for (int i = 1; i <= lenr; i++)
16         c[i] = a[mid+i];
17     c[lenr+1] = INF;
18     int i = 1 ,j = 1,k = s;
19     while(k <= t)
20     {
21         if (b[i] <= c[j])
22             a[k++] = b[i++];
23         else
24         {
25             a[k++] = c[j++];
26             ans+=lenl-i+1; //计算逆序数
27         }
28     }
29     delete(b);
30     delete(c);
31 }
32 void MergeSort(int *a,int s,int t)
33 {
34     int mid = (s+t)>>1;
35     if(t <= s)
36         return ;
37     MergeSort(a,s,mid);
38     MergeSort(a,mid+1,t);
39     Merge(a,s,mid,t);
40 }
41 int main()
42 {
43     int t,o = 0,a[N],b[N];
44     scanf("%d",&t);
45     while(t--)
46     {
47         o++;
48         int n;
49         ans = 0;
50         scanf("%d",&n);
51         for (int i = 1; i <= n; i++)
52             scanf("%d",&a[i]);
53         MergeSort(a,1,n);
54         printf("Scenario #%d:
%lld

",o,ans);
55     }
56     return 0;
57 }
View Code

法三:树状数组 o(nlogn)

 1 #include <stdio.h>
 2 #include <string.h>
 3 #include <algorithm>
 4 using namespace std;
 5 const int N=2000005;
 6 int c[N],a[N],n;
 7 struct node
 8 {
 9     int data;
10     int pos;
11     friend bool operator < (const node a,const node b)
12     {
13         if(a.data==b.data)
14             return a.pos < b.pos;
15         else
16             return a.data < b.data;
17     }
18 } g[N];
19 int lowbit(int x)
20 {
21     return x&(-x);
22 }
23 void update(int x,int data)
24 {
25     while(x <= N)
26     {
27         c[x]+=data;
28         x+=lowbit(x);
29     }
30 }
31 int sum(int x)
32 {
33     int ans = 0;
34     while(x > 0)
35     {
36         ans+=c[x];
37         x-=lowbit(x);
38     }
39     return ans;
40 }
41 int main()
42 {
43     int t,o = 0;
44     scanf("%d",&t);
45     while(t--)
46     {
47         o++;
48         scanf("%d",&n);
49         for (int i = 1; i <= n; i++)
50         {
51             scanf("%d",&g[i].data);
52             g[i].pos = i;
53         }
54         sort(g+1,g+1+n);
55         memset(c,0,sizeof(c));
56         for (int i = 1; i <= n; i++)//离散化
57             a[g[i].pos] = i;
58         long long ans = 0;
59         for (int i = 1; i <= n; i++)
60         {
61             update(a[i],1);
62             ans+=i-sum(a[i]);
63         }
64         printf("Scenario #%d:
%lld

",o,ans);
65     }
66     return 0;
67 }
View Code
原文地址:https://www.cnblogs.com/lahblogs/p/3268485.html