首页 > 编程语言 > 详细

POJ 2299 求逆序对(归并排序或树状数组)

时间:2015-03-10 22:46:04      阅读:2230      评论:0      收藏:0      [点我收藏+]
Ultra-QuickSort
Time Limit: 7000MS   Memory Limit: 65536K
Total Submissions: 45290   Accepted: 16440

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

Source

归并排序做法:
 1 #include<iostream>
 2 #include<algorithm>
 3 #include<cstdio>
 4 #include<cstring>
 5 #include<algorithm>
 6 #include<cstdlib>
 7 #include<string>
 8 using namespace std;
 9 int num[ 500007],num1[500007],num2[5000007];
10 int n;
11 long long ans=0;
12 void get(int left,int mid,int right)
13 {
14     for(int i=left;i<=right;i++)  num1[i]=num[i];
15     int sum=(mid-left)+1;
16     int i=left,j=mid+1,k=left;
17     while(i<=mid&&j<=right){
18         if(num1[i]<=num1[j]){
19             num[k++]=num1[i++];
20         }
21         else
22         {
23           num[k++]=num1[j++];
24           ans+=(mid-i+1);
25         }
26     }
27     while(i<=mid){num[k++]=num1[i++];}
28     while(j<=right){num[k++]=num1[j++];}
29 }
30 
31 void merge1(int l,int r)
32 {
33       if(l<r){
34 
35         int m=(l+r)>>1;
36         merge1(l,m);
37         merge1(m+1,r);
38         get(l,m,r);
39     }
40 }
41 int main()
42 {
43  //  freopen("in.txt","r",stdin);
44     while(1){
45         scanf("%d",&n);
46         ans=0;
47         if(n==0) break;
48         for(int i=0;i<n;i++)
49             scanf("%d",&num[i]);
50         merge1(0,n-1);
51         printf("%I64d\n",ans);
52     }
53     return 0;
54 }

树状数组做法:

 1 #include <iostream>
 2 #include<cstdio>
 3 #include<cstring>
 4 #include<cstdlib>
 5 #include<cstring>
 6 #include<algorithm>
 7 #define MAX  500010
 8 #define LL long long
 9 using namespace std;
10 int num[MAX],tree[MAX];
11 int n;
12 LL ans=0;
13 struct node
14 {
15     int value,sum;
16 };
17 node arr[MAX];
18 int lowbit(int value)
19 {
20     return value&(-value);
21 }
22 void build(int value)
23 {
24   while(value<=n){
25     tree[value]+=1;
26     value+=lowbit(value);
27   }
28 }
29 int Get_sum(int value)
30 {
31     int result=0;
32   for(int i=value;i>=1;i-=lowbit(i))
33     {
34         result+=tree[i];
35     }
36     return result;
37 }
38 bool cmp(node n1,node n2)
39 {
40     return n1.value<n2.value;
41 }
42 int main()
43 {
44     //freopen("in.txt","r",stdin);
45  while(scanf("%d",&n)==1 && n)
46     {
47         ans=0;
48         memset(tree,0,sizeof(tree));
49         for(int i=1;i<=n;i++) scanf("%d",&arr[i].value),arr[i].sum=i;
50         sort(arr+1,arr+n+1,cmp);
51         for(int i=1;i<=n;i++)
52         {
53             num[arr[i].sum]=i;
54         }
55         for(int i=1;i<=n;i++)
56         {
57             build(num[i]);
58             ans+=i-Get_sum(num[i]);
59         }
60         printf("%I64d\n",ans);
61     }
62     return 0;
63 }

 

POJ 2299 求逆序对(归并排序或树状数组)

原文:http://www.cnblogs.com/codeyuan/p/4328492.html

(0)
(1)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!