• 归并排序求逆序数


    poj 2299

    一个乱序序列的 逆序数 = 在只允许相邻两个元素交换的条件下,得到有序序列的交换次数

    归并排序的思想:先递归把序列拆分,然后合并

    mergetsort(int start,int last)
    {
       if(start<last)
       {
             mid=(start+last)/2;
             mergetsort(start,mid);
             mergetsort(mid+1,last);
             mergetSort(start,last);  // 合并函数
    
       }
    }

    合并函数:

    void mergesort(int first,int mid,int last)
    {
       /* printf("first:%d,mid:%d,last:%d
    ",first,mid,last);
    
        for(int i=0;i<=mid;i++)
            printf("%d ",a[i]);
        printf("
    ");
        for(int i=mid+1;i<last;i++)
            printf("%d ",a[i]);
        printf("
    ");
        printf("-------------
    ");*/
    
    
        int i=first,j=mid+1;
        int k=0;
        while(i<=mid&&j<=last)
        {
            if(a[i]<a[j])
            {
                temp[k++]=a[i];
                i++;
            }
            else{
               temp[k++]=a[j];
               t=t+mid-i+1;
               j++;
            }
        }
        while(i<=mid)
        {
            temp[k++]=a[i];
            i++;
        }
        while(j<=last)
        {
            temp[k++]=a[j];
            j++;
        }
        for(int c=0;c<k;c++)
        {
            a[first+c]=temp[c];
        }
    
    }

    需要注意的是t=t+mid-i+1,t即是所求的逆序数。

    比如序列91054,在第二次合并190时,0比1小,那么0肯定也会比1后面的9要小,所以0要移动两次,即9和1的逆序数都要加1,那么mid-i+1求的是从比0大的这个数开始到mid一共有多少个数。

    所有代码:

    #include <iostream>
    #include <cstdio>
    
    using namespace std;
    
    int a[500005];
    int temp[500005];
    __int64 t=0;
    
    
    
    void mergesort(int first,int mid,int last)
    {
       /* printf("first:%d,mid:%d,last:%d
    ",first,mid,last);
    
        for(int i=0;i<=mid;i++)
            printf("%d ",a[i]);
        printf("
    ");
        for(int i=mid+1;i<last;i++)
            printf("%d ",a[i]);
        printf("
    ");
        printf("-------------
    ");*/
    
    
        int i=first,j=mid+1;
        int k=0;
        while(i<=mid&&j<=last)
        {
            if(a[i]<a[j])
            {
                temp[k++]=a[i];
                i++;
            }
            else{
               temp[k++]=a[j];
               t=t+mid-i+1;
               j++;
            }
        }
        while(i<=mid)
        {
            temp[k++]=a[i];
            i++;
        }
        while(j<=last)
        {
            temp[k++]=a[j];
            j++;
        }
        for(int c=0;c<k;c++)
        {
            a[first+c]=temp[c];
        }
    
    }
    
    
    void mergeSort(int first,int last)
    {
        if(first<last)
        {
            int mid=(first+last)/2;
            mergeSort(first,mid);
            mergeSort(mid+1,last);
            mergesort(first,mid,last);
        }
    
    }
    
    int main()
    {
        int n;
        //freopen("a.txt","rw",stdin);
        do{
            t=0;
            scanf("%d",&n);
            if(n==0) break;
            for(int i=0;i<n;i++)
            {
                scanf("%d",&a[i]);
            }
            mergeSort(0,n-1);
            printf("%I64d
    ",t);
        }while(true);
        return 0;
    }

    除了归并排序以外,树状数组也可以用来求解。

    下次学习。

  • 相关阅读:
    ps -aux --sort -rss |head 列出进程拿物理内存占用排序 使用ps aux 查看系统进程时,第六列即 RSS列显示的就是进程使用的物理内存。
    13 memcache服务检查
    shell 颜色
    expr判断整数是相加的值,返回命令的返回值$? 是0,但是少数情况是1,例如1 + -1 ,$? 的结果是1 ,判断要大于1最准确
    ZABBIX监控原理
    ansible分发密钥
    再来一个expect脚本
    11:菜单自动化软件部署经典案例
    19:批量检查多个网站地址是否正常
    数组迭代
  • 原文地址:https://www.cnblogs.com/Qmelbourne/p/6709366.html
Copyright © 2020-2023  润新知