点击打开题目链接
超级快速排序法是通过不断交换两个相邻元素直到序列为升序来完成的。
现给出一组非负整数,求解应用超快速排序法排序这组整数所必需的交换操作的次数。
求逆序数。
一、线段树(树状数组):
对于每个元素来说,必要移动次数等于位于它之前且大于它的元素的个数,而答案即所有元素的必要移动次数之和。
定义一个数组Sorted为原数组Orig的升序排序数组(使用STL的sort函数),对于Orig的中每个元素cur依次执行以下操作:
1、查找cur在Sorted中的位置loc(使用二分查找)。
2、查询并累加当前线段树(树状数组)中loc后的元素个数sum(sum即在Orig中位于cur之前且大于cur的元素个数)。
3、插入cur在线段树(树状数组)的loc位置。
最后输出答案即可(注意答案需要用64位整形来保存)。
二、归并排序:
就是归并排序啦!
1、线段树
#include<cstdio> #include<cstring> #include<algorithm> using namespace std; #define LSON(N) ((N)<<1 ) #define RSON(N) ((N)<<1|1) #define MID(L,R) (((L)+(R))>>1) const int MAXN=500005; int N,Orig[MAXN],Sorted[MAXN],SegmTree[MAXN<<2]; int BinSearch(int Num,int L,int R) //Binary Search:二分查找 { int M=MID(L,R); if(Num<Sorted[M]) return BinSearch(Num,L,M-1); if(Num>Sorted[M]) return BinSearch(Num,M+1,R); return M; } void Bulid() { memset(SegmTree,0,sizeof(SegmTree)); } void Insert(int Ins,int L,int R,int N) { ++SegmTree[N]; if(L!=R) { int M=MID(L,R); if(Ins<=M) Insert(Ins,L,M,LSON(N)); else Insert(Ins,M+1,R,RSON(N)); } } int Query(int Que,int L,int R,int N) { if(Que<L) return SegmTree[N]; if(R<=Que) return 0; int M=MID(L,R); return Query(Que,L,M,LSON(N))+Query(Que,M+1,R,RSON(N)); } int main() { while(scanf("%d",&N)==1&&N) { Bulid(); for(int i=0;i<N;++i) { scanf("%d",&Orig[i]); Sorted[i]=Orig[i]; } sort(Sorted,Sorted+N); long long sum=0; for(int i=0;i<N;++i) { int loc=BinSearch(Orig[i],0,N-1); sum+=Query(loc,0,499999,1); Insert(loc,0,499999,1); } printf("%lld\n",sum); } return 0; }
2、树状数组
#include<cstdio> #include<cstring> #include<algorithm> using namespace std; #define MID(L,R) (((L)+(R))>>1) #define LOWBIT(N) ((N)&(-(N))) const int MAXN=500005; int N,Orig[MAXN],Sorted[MAXN],BinTree[MAXN<<2]; int BinSearch(int Num,int L,int R) //Binary Search:二分查找 { int M=MID(L,R); if(Num<Sorted[M]) return BinSearch(Num,L,M-1); if(Num>Sorted[M]) return BinSearch(Num,M+1,R); return M; } void Build() { memset(BinTree,0,sizeof(BinTree)); } void UpDate(int X) { while(X<=N) { ++BinTree[X]; X+=LOWBIT(X); } } long long GetSum(int X) { long long sum=0; while(X) { sum+=BinTree[X]; X-=LOWBIT(X); } return sum; } int main() { while(scanf("%d",&N)==1&&N) { Build(); for(int i=0;i<N;++i) { scanf("%d",&Orig[i]); Sorted[i]=Orig[i]; } sort(Sorted,Sorted+N); long long sum=0; for(int i=0;i<N;++i) { int loc=BinSearch(Orig[i],0,N-1); sum+=GetSum(N)-GetSum(loc+1); UpDate(loc+1); } printf("%lld\n",sum); } return 0; }
3、归并排序
#include<stdio.h> int N,Num[500005]; long long Sum; void Merge(int *Array,int L,int M,int R) { int move1=0,move2=0,move3=0,*tmp=new int[R-L+1]; while(L+move1<=M&&M+1+move2<=R) { if(Array[L+move1]<=Array[M+1+move2]) { tmp[move3++]=Array[L+(move1++)]; } else { Sum+=M-(L+move1)+1; tmp[move3++]=Array[M+1+(move2++)]; } } while(L+move1<=M) { tmp[move3++]=Array[L+(move1++)]; } while(move3--) { Array[L+move3]=tmp[move3]; } delete tmp; } void MergeSort(int *Array,int L,int R) { if(L<R) { int M=(L+R)>>1; MergeSort(Array,L,M); MergeSort(Array,M+1,R); Merge(Array,L,M,R); } } int main() { while(scanf("%d",&N)==1&&N) { Sum=0; for(int i=0;i<N;++i) { scanf("%d",&Num[i]); } MergeSort(Num,0,N-1); printf("%lld\n",Sum); } return 0; }