求逆序对
Posted cutepota
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了求逆序对相关的知识,希望对你有一定的参考价值。
给定一个序列a1,a2,…,an,如果存在iaj,那么我们称之为逆序对,求逆序对的数目
Input
第一行为n,表示序列长度,接下来的n行,第i+1行表示序列中的第i个数。
N<=10^5。Ai<=10^5
N<=10^5。Ai<=10^5
Output
两行,第一行为所有逆序对总数,第二行为本质不同的逆序对总数。
Sample Input
4
3
2
3
2
Sample Output
3 1
sol:利用归并排序的思想求逆序对。
归并排序的核心思想是分治,当我们将a数组里的数分得足够小的时候,开始逐一合并过程,合并时,分别用指针i,j指向两边的头(即i=l, j=mid+1),分别往后扫,每次取出两个指针所指的数中较小的放入b数组。如果取出的是左边的数放入b数组,则左右两边的数不构成逆序对,如果是右边的数放入b数组,这时a[i]>a[j],说明i~mid间的所有数都比a[j]大(因为左边有序,右边有序),此时,逆序对数增加mid-i+1个。
1 #include <cstdio> 2 int a[30010],b[30010]; 3 int ans=0; 4 int n; 5 void merge(int s,int t) 6 //s是左边界,t是右边界 7 { 8 if(s==t)return; 9 int mid=s+t>>1; 10 merge(s,mid); //左边排好 11 merge(mid+1,t);//右边排好 12 int i=s,j=mid+1; 13 int p=s-1;//记一个位置 14 while(i<=mid&&j<=t) //但没有过界的时候 15 { 16 if(a[i]<=a[j]) //将a[i]放入b数组 17 { 18 b[++p]=a[i]; 19 i++; 20 } 21 else 22 { 23 b[++p]=a[j];//将a[j]放入b数组 24 j++; 25 ans+=mid+1-i;//逆序对增加mid+1-i个 26 } 27 } 28 while(j<=t)//把a[j]剩下的全部放入b数组 29 { 30 b[++p]=a[j]; 31 j++; 32 } 33 while(i<=mid)//把a[i]剩下的全部放入b数组 34 { 35 b[++p]=a[i]; 36 i++; 37 } 38 for(int i=s;i<=t;i++) 39 a[i]=b[i]; 40 } 41 int main() 42 { 43 scanf("%d",&n); 44 for(int i=1;i<=n;i++) 45 scanf("%d",&a[i]); 46 merge(1,n); 47 printf("%d",ans); 48 }
以上是关于求逆序对的主要内容,如果未能解决你的问题,请参考以下文章