逆序对
逆序对
逆序对:满足i<j且a[i]>a[j]的所有的(a[i],a[j])对的个数。
I.正常的方法O(n^2):
可以从i或j的角度出发
Code:
1 #include <stdio.h> 2 #include <stdlib.h> 3 #define maxn 10000 4 5 int main() 6 { 7 long a[maxn+1],n,ans,i,j; 8 scanf("%ld",&n); 9 for (i=1;i<=n;i++) 10 scanf("%ld",&a[i]); 11 ans=0; 12 //i<j 13 for (i=1;i<n;i++) 14 for (j=i+1;j<=n;j++) 15 //a[i]>a[j] 16 if (a[i]>a[j]) 17 ans++; 18 printf("%ld\n",ans); 19 ans=0; 20 //i>j 21 for (i=n;i>1;i--) 22 for (j=i-1;j>=1;j--) 23 //a[i]<a[j] 24 if (a[i]<a[j]) 25 ans++; 26 printf("%ld\n",ans); 27 return 0; 28 } 29 /* 30 10 31 5 3 2 10 1 6 9 4 8 7 32 4+2+1+6+0+1+3+0+1+0=18 33 3+2+4+1+1+4+0+2+1+0=18 34 */
II.有两种方法求逆序对使得时间复杂度为O(nlogn):
1.归并排序+统计
2.离散化+树状数组
1.归并排序+统计
1 Code: 2 #include <stdio.h> 3 #include <stdlib.h> 4 #define maxn 100000 5 6 ///mergesort:O(nlogn) 7 8 long a[maxn+1],t[maxn+1]; 9 //max_ans:maxn*(maxn-1)/2=4999950000 , use long long 10 long long ans=0; 11 12 13 void mergesort(long l,long r) 14 { 15 if (l==r) 16 return ; 17 long mid,x,y,z,i; 18 mid=(l+r)/2; 19 mergesort(l,mid); 20 mergesort(mid+1,r); 21 for (i=l;i<=r;i++) 22 t[i]=a[i]; 23 x=l; 24 y=mid+1; 25 z=l; 26 while (x<=mid && y<=r) 27 { 28 //两个数相等时让左边的数先加,因为相同的数不能凑成一对 29 if (t[x]<=t[y]) 30 { 31 a[z]=t[x]; 32 x++; 33 //a[x] > a[mid+1]~a[y-1] 34 ans+=(y-mid-1); 35 } 36 else if (t[x]>t[y]) 37 { 38 a[z]=t[y]; 39 y++; 40 } 41 z++; 42 } 43 if (x<=mid) 44 { 45 //a[x] > a[mid+1]~a[r] 46 ans+=(mid-x+1)*(r-mid); 47 while (z<=r) 48 { 49 a[z]=t[x]; 50 x++; 51 z++; 52 } 53 } 54 else 55 { 56 while (z<=r) 57 { 58 a[z]=t[y]; 59 y++; 60 z++; 61 } 62 } 63 } 64 65 int main() 66 { 67 long n,i; 68 scanf("%ld",&n); 69 for (i=1;i<=n;i++) 70 scanf("%ld",&a[i]); 71 mergesort(1,n); 72 printf("%lld\n",ans); 73 return 0; 74 } 75 /* 76 Input: 77 10 78 5 3 2 10 1 6 9 4 8 7 79 Output: 80 18 81 */
2.离散化+树状数组
Code:
1 #include <stdio.h> 2 #include <stdlib.h> 3 #define maxn 10000 4 5 //离散化(数为1~n;或数很集中除外)+树状数组(求a[k+1]~a[n]中小于a[k]的数) 6 7 struct node 8 { 9 long value,pos; 10 }s[maxn+1]; 11 //n个数,最多有n个不同的数值 12 long a[maxn+1],c[maxn+1]; 13 14 int cmp(const void *a,const void *b) 15 { 16 if ((*(struct node *)a).value<(*(struct node *)b).value) 17 return -1; 18 else 19 return 1; 20 } 21 22 int main() 23 { 24 long n,i,t,v; 25 long long ans; 26 scanf("%ld",&n); 27 for (i=1;i<=n;i++) 28 { 29 scanf("%ld",&s[i].value); 30 s[i].pos=i; 31 } 32 //排序 33 qsort(s+1,n,sizeof(struct node),cmp); 34 //离散化(保留数的大小关系;数值无所谓,舍弃之) 35 //设置最小值为2,是为了之后比(a[i]-1)小的数 36 t=1; 37 for (i=1;i<=n;i++) 38 { 39 t++; 40 a[s[i].pos]=t; 41 while (i<n && s[i].value==s[i+1].value) 42 { 43 i++; 44 a[s[i].pos]=t; 45 } 46 } 47 //树状数组 48 for (i=1;i<=t;i++) 49 c[i]=0; 50 ans=0; 51 for (i=n;i>=1;i--) 52 { 53 //获得小于等于(a[i]-1),即小于a[i]的数 54 v=a[i]-1; 55 while (v>0) 56 { 57 ans+=c[v]; 58 v=v-(v & (-v)); 59 } 60 //添加a[i] 61 v=a[i]; 62 while (v<=t) 63 { 64 c[v]++; 65 v=v+(v & (-v)); 66 } 67 } 68 printf("%lld\n",ans); 69 return 0; 70 } 71 /* 72 Input: 73 10 74 5 3 2 10 1 6 9 4 8 7 75 Output: 76 18 77 */ 78