zoukankan      html  css  js  c++  java
  • 归并排序求逆序对

    【题目描述】

    现给定1,2,…,n的一个排列,求它的逆序数。

    【输入格式】

    第一行是一个整数n,表示该排列有n个数(n <= 100000)。
    第二行是n个不同的正整数,之间以空格隔开,表示该排列。

    【输出格式】

    输出该排列的逆序数。

    【分析】

    (1)将区间[1..n]进行二分,先求出区间[1,mid]和[mid+1,n],而子区间又进行二分直到区间内只有一个元素。

    (2)将已经排好序的子区间进行合并,即用有序的[L,K][K+1,R]求出有序的区间[L,R]最终合并成区间[1,N],而合并区间分为若干步:

    ①令i=j,j=mid+1,变量k=L,执行下一步。

    ②如果i<=mid,且j<=r,若a[i]<a[j],则令c[sum]=a[i],i++,sum++;

    若a[i]>=a[j],则令c[sum]=a[j],j++,sum++,执行下一步,如果i>k,或j>r,则把令一个区间的剩下元素都放到c数组中,执行下一步。

    ③如果sum>r,则跳出循环。

    求逆序对:在合并区间的第二步中在a[i]<a[j]中ans+=mid-i+1就可以了,说明a[j]比区间[i,mid]中的任何一个元素都要小,而且位置又在j的前面,提供了mid-i+1个逆序对。

    【代码】

     1 #include<bits/stdc++.h>
     2 
     3 using namespace std;
     4 
     5 typedef long long LL;
     6 
     7 int a[100010],c[100010];
     8 int n;
     9 LL ans=0;
    10 
    11 void merge_sort(int l,int r){
    12     int mid=(l+r)>>1,i=l,j=mid+1,k;
    13     if(l>=r)return;
    14     merge_sort(l,mid);
    15     merge_sort(mid+1,r);
    16     k=l;
    17     while(i<=mid&&j<=r){
    18         if(a[i]>a[j]){
    19             c[k++]=a[j++];
    20             ans+=mid-i+1;
    21         }
    22         else c[k++]=a[i++];
    23     }
    24     while(i<=mid)c[k++]=a[i++];
    25     while(j<=r)c[k++]=a[j++];
    26     for(i=l;i<=r;i++) a[i]=c[i];
    27 }
    28 
    29 int main()
    30 {
    31     scanf("%d",&n);
    32     for(int i=1;i<=n;i++)scanf("%d",&a[i]);
    33     merge_sort(1,n);
    34     printf("%lld
    ",ans);
    35     return 0;
    36 }
    黎明的朝阳,会为苦难中最坚强的信念升起
  • 相关阅读:
    Hadoop启动报Error: JAVA_HOME is not set and could not be found
    mrjob在hadoop上跑的时候,报错
    Hadoop3安装踩坑 there is no HDFS_NAMENODE_USER defined. Aborting operation.
    mrjob 运行报错
    站位

    Lua基本数据类型
    常量指针和指针常量
    C基础题
    C++拷贝构造函数(深拷贝,浅拷贝)
  • 原文地址:https://www.cnblogs.com/Dawn-Star/p/9113934.html
Copyright © 2011-2022 走看看