标签:algo 归并排序 思路 closed 逆序对 hide 数列 查找 排序算法
题目大意:
定义一种新的排序算法:随机的选一个数,若比它后一个大就交换,直到后一个比它小,完成一次操作。现在给定一个n个数的数列(保证是1~n的一个排列),问最少随机多少次?(T ≤ 200)(1 ≤ N ≤ 10 6).
思路:
对于每一个数,查看它与后面的数是否能构成逆序对就好。查找逆序对用归并排序时间复杂度就够了。
若从小到大排, 在归并排序每次合并两个区间时,左边的ai若大于右边的aj就说明aj与左边的区间的所有数都构成逆序对。这里要找每个数是否与后面的构成,就可以到过来记录,在按从大到小做归并排序。
1 #include<cstdio> 2 #include<cstring> 3 #include<algorithm> 4 #include<cstdlib> 5 6 using namespace std; 7 8 int T,n,a[1000005],aa[1000005],anti[1000005]; 9 10 void msort(int l,int r) 11 { 12 int mid=(l+r)/2; 13 if(l+1<r) 14 { 15 msort(l,mid); 16 msort(mid,r); 17 } 18 int i=l,j=mid; 19 int k=l; 20 while(i<mid&&j<r) 21 { 22 if(a[i]>a[j]) 23 { 24 aa[k]=a[i]; 25 i++;k++; 26 } 27 else 28 { 29 anti[a[j]]++; 30 aa[k]=a[j]; 31 k++;j++; 32 } 33 } 34 if(j<r) 35 { 36 aa[k]=a[j]; 37 j++;k++; 38 } 39 if(i<mid) 40 { 41 aa[k]=a[i]; 42 i++;k++; 43 } 44 } 45 46 int main() 47 { 48 scanf("%d",&T); 49 for(int I=1;I<=T;I++) 50 { 51 scanf("%d",&n); 52 memset(a,0,sizeof(a)); 53 memset(anti,0,sizeof(anti)); 54 memset(aa,0,sizeof(aa)); 55 for(int i=1;i<=n;i++)scanf("%d",&a[n+1-i]); 56 msort(1,n+1); 57 int ans=0; 58 for(int i=1;i<=n;i++) 59 { 60 if(anti[i])ans++; 61 } 62 printf("Case #%d: %d\n",I,ans); 63 } 64 return 0; 65 }
标签:algo 归并排序 思路 closed 逆序对 hide 数列 查找 排序算法
原文地址:https://www.cnblogs.com/LiqgNonqfu/p/9748832.html