zoukankan      html  css  js  c++  java
  • ACM_逆序数(归并排序)

    帮挂科

    Time Limit: 2000/1000ms (Java/Others) 64bit IO Format: %lld & %llu

    Problem Description:

    冬瓜发现期末很多人都挂了线代,他决定写个程序帮挂科的同学。在一个排列中,如果一对数的前后位置与大小
    顺序相反,即前面的数大于后面的数,那么它们就称为一个逆序。一个排列中逆序的总数就称为这个排列的逆序数。
    可是冬瓜想的头发都掉光了,聪明的你肯定能够帮帮他。

    Input:

    输入有多组
    第1行:N,N为序列的长度(n <= 50000)
    第2 - N + 1行:序列中的元素(0 <= A[i] <= 10^9)

    Output:

    输出逆序数

    Sample Input:

    4
    2
    4
    3
    1

    Sample Output:

    4
    解题思路:这里用归并排序求逆序数。主要是将序列分成两部分,只要在有序的前半部分中找到的下标i比后半部分下标j大,那么下标i~m都可以构成逆序数对,即有(m-i+1)对,再合并子序列即可。。。
    AC代码:
     1 #include<bits/stdc++.h>
     2 using namespace std;
     3 const int N=50005;
     4 int ans,n,a[N],tmp[N];//tmp是临时数组
     5 void _merge(int l,int m,int r)//合并子序列
     6 {
     7     int i=l,j=m+1,k=l;
     8     while(i<=m && j<=r){
     9         if(a[i]>a[j]){
    10             tmp[k++]=a[j++];//从小到大排列
    11             ans+=m-i+1;//只要a[i]>a[j],i~m都可以构成逆序数
    12         }
    13         else tmp[k++]=a[i++];//相等的就直接存放到临时数组
    14     }
    15     while(i<=m)tmp[k++]=a[i++];//剩余的直接拷贝
    16     while(j<=r)tmp[k++]=a[j++];
    17     for(int i=l;i<=r;++i)
    18         a[i]=tmp[i];//临时数组赋值给a数组
    19 }
    20 void _merge_sort(int l,int r)//归并排序
    21 {
    22     if(l<r){
    23         int m=(l+r)>>1;//分成两部分
    24         _merge_sort(l,m);//左递归
    25         _merge_sort(m+1,r);//右递归
    26         _merge(l,m,r);//合并两部分
    27     }
    28 }
    29 int main()
    30 {
    31     while(cin>>n){
    32         for(int i=0;i<n;++i)
    33             cin>>a[i];
    34         ans=0;
    35         _merge_sort(0,n-1);
    36         cout<<ans<<endl;
    37     }
    38     return 0;
    39 }
    
    
  • 相关阅读:
    java实现前n项和,要求不使用循环、乘除法、判断标识
    java 线程池 带返回值
    java 多线程 数据通信
    jedis使用分布式锁
    记一次自定义管理工厂使用spring自动装载bean
    面试题玩数组
    记一次随便排序算法
    九九乘法表打印记一次al面试
    多线程操作共享变量顺序输出abc 记一次al面试题
    博客迁移
  • 原文地址:https://www.cnblogs.com/acgoto/p/8605847.html
Copyright © 2011-2022 走看看