又是好长时间没有写博客了,刚参加完成都赛区的亚洲赛,尽管和两位学长一起努力得了一个铜奖,但是感觉自己和那里其他大牛的差距太大!
所以,我决定要利用接下来一年的时间学好算法,好好努力,目标是明年亚洲赛 拿一块金奖!
下面介绍一下用归并排序求逆序数!感觉有一点和线段树很相似,就是从中间分开!
归并排序法是将两个(或两个以上)有序表合并成一个新的有序表,即把待排序序列分为若干个子序列,每个子序列是有序的。然后再把有序子序列合并为整体有序序列。
归并操作的工作原理如下:
1、 申请空间,使其大小为两个已经排序序列之和,该空间用来存放合并后的序列
2、 设定两个指针,最初位置分别为两个已经排序序列的起始位置
3、 比较两个指针所指向的元素,选择相对小的元素放入到合并空间,并移动指针到下一位置
4、 重复步骤3直到某一指针达到序列尾 将另一序列剩下的所有元素直接复制到合并序列尾
重要用途 : 可以用来求逆序对数!
代码如下(既排序带求逆序数):
# include<stdio.h> int count; void merge(int array[],int p,int q,int r) ///// p < = q < r { int begin1,end1,begin2,end2,k,temp[1000]; begin1=p; end1=q; begin2=q+1; end2=r; k=0; while(begin1<=end1 && begin2<=end2) { if(array[begin1] < array[begin2]) { temp[k++]=array[begin1]; begin1++; count+=begin2-(q+1); } else { temp[k++]=array[begin2]; begin2++; } } while(begin1<=end1) { temp[k++]=array[begin1]; begin1++; count+=end2-q; } while(begin2<=end2) { temp[k++]=array[begin2]; begin2++; } for(int i=p;i<=r;i++) array[i]=temp[i-p]; } void mergesort(int array[],int first,int last) { int mid=(first+last)/2; if(first<last) { mergesort(array,first,mid); mergesort(array,mid+1,last); merge(array,first,mid,last); } } int main() { int i,n,array[1000]; while(scanf("%d",&n)!=EOF) { for(i=1;i<=n;i++) scanf("%d",&array[i]); count=0; mergesort(array,1,n); for(i=1;i<=n;i++) printf("%d ",array[i]); printf("\n"); printf("%d\n",count); } return 0; }