在一个排列中,如果一对数的前后位置与大小顺序相反,即前面的数大于后面的数,那么它们就称为一个逆序。一个排列中逆序的总数就称为这个排列的逆序数。
如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 ",sum); 52 }