51Nod-1019 逆序数 (归并排序)

基准时间限制:1 秒 空间限制:131072 KB 分值: 0  难度:基础题
 收藏
 关注
在一个排列中,如果一对数的前后位置与大小顺序相反,即前面的数大于后面的数,那么它们就称为一个逆序。一个排列中逆序的总数就称为这个排列的逆序数。
 
如2 4 3 1中,2 1,4 3,4 1,3 1是逆序,逆序数是4。给出一个整数序列,求该序列的逆序数。
Input
第1行:N,N为序列的长度(n <= 50000)
第2 - N + 1行:序列中的元素(0 <= A[i] <= 10^9)
Output
输出逆序数
Input示例
4
2
4
3
1
Output示例
4

题意:如果前面的数字比它后面的数字大,那么逆序数加1。
emmm原本这题我用冒泡写的因为冒泡就是比较这个数和后面数的大小,这样非常好求逆排序,但是冒泡时间太长了.....所以过不了。
归并排序(速度仅次于快速排序,为稳定排序算法);

那么问题来了,逆序数又该怎么求呢?


拿这一步举例子:当比到2>4的时候,排序后3的位子则位4(大家学了归并排序都知道),那么这一步就要让逆序数+4,想必你聪明的你已经想到了,对,因为2大于1所以表明2以及2后面的所有数(这里只有2,3,5,7)都大于1;
所以逆序数的计算就是if(a[i]>a[j]) 逆序数+=mid-i+1;//i,j下面的代码中可以看到指代什么。好了废话不多说看代码。
 1 #include<stdio.h>
 2 #include<iostream>
 3 using namespace std;
 4 long long sum=0;
 5 void merge(int a[],int left,int mid,int right,int b[])
 6 {
 7     int i=left;
 8     int j=mid+1;
 9     int t=0;
10     while(i<=mid&&j<=right)
11     {
12         if(a[i]<=a[j])
13         {
14             b[t++]=a[i++];
15         }
16         else
17         {
18             sum+=mid-i+1;//求逆序数 
19             b[t++]=a[j++];
20         }
21     }
22     while(i<=mid)
23     b[t++]=a[i++];
24     while(j<=right)
25     b[t++]=a[j++];
26     t=0;
27     while (left<=right)
28     {
29         a[left++]=b[t++];
30     }
31 }
32 void sort1(int a[],int left,int right,int b[])
33 {
34     if(left<right)
35     {
36         int mid=(left+right)/2;
37         sort1(a,left,mid,b);
38         sort1(a,mid+1,right,b);
39         merge(a,left,mid,right,b);
40     }
41 }
42 int main()
43 {
44     int a[50005];
45     int b[50005];
46     int N;
47     scanf("%d",&N);
48     for (int i=0;i<N;i++)
49     cin>>a[i];
50     sort1(a,0,N-1,b);
51     printf("%d\n",sum);
52 }
 
  
  
 

猜你喜欢

转载自www.cnblogs.com/bendandedaima/p/9340060.html
今日推荐