nyoj 322 117 求逆序数 归并排序

来源:互联网 发布:匡恩网络招聘 编辑:程序博客网 时间:2024/06/05 20:12

此题相当于问冒泡从小大大排序中交换了多少次,但是冒泡的时间复杂度的n^2,所以不可取,可以换用归并排序,归并排序时间复杂度为nlogn,还行,之前只听过归并排序的概念(毕竟有sort),没有敲过代码,这次参考别人的博客水一发,
比如现在有两组已经从小到大排好的数据 5 10 15 17和3 9 11 12 30
要将这两组数据整合到一起,同时按从小到大排序
那么可以先比较两组数据的第一个数字 5 和3,3小,取3,同时去掉3,再比较5 和9,取5同时去掉5,再比较10和9,9小取9同时去掉,以此类推,得到3 5 9 10 11 12 15 17 30 如果现在有一组数据要排大小的话,我们就可以将这一组数据分成两组,同时这两组的每一组再分成两组,直到每组数据为两个数(也可能为1个数),然后比较排序,这样就得到了已经排好序的数据,再两两比较类似于上面的例子,重新整合到一块。
概念容易理解,但是代码不是很好理解:

#include<stdio.h>int a[1000010],b[1000010];long long s=0;void sort(int first,int mid,int last){    int i=first,k=first,j=mid+1;    while(i<=mid&&j<=last)  //先将左一半或右一半的数据取完,    {        if(a[i]<=a[j])            b[k++]=a[i++];        else            s+=j-k,b[k++]=a[j++];    //s+=j-k是关键,想想为什么,^_^    }    while(i<=mid)  //剩下的数据均是大的,所以取完 因为不知道到底是左一半先取完还是右一半先取完,所以两者都尝试        b[k++]=a[i++];    while(j<=last)//剩下的数据均是大的,所以取完        b[k++]=a[j++];    for(i=first; i<=last; i++)  //再重新将b[]赋值给a[]        a[i]=b[i];}void msort(int first,int last){    int mid=(first+last)/2;    if(first<last)  //一直递归直到first==last        msort(first,mid),msort(mid+1,last),sort(first,mid,last);  //先把左一半和右一半排序,然后再整合}int main(){    int nn;    scanf("%d",&nn);    while(nn--)    {        int n,i;        scanf("%d",&n);        for(i=1; i<=n; i++)            scanf("%d",&a[i]);        s=0;        msort(1,n);        printf("%lld\n",s);    }}
1 0
原创粉丝点击