一.题目

题目1 : 二分·归并排序之逆序对

时间限制:10000ms
单点时限:1000ms
内存限制:256MB

描写叙述

在上一回、上上回以及上上上回里我们知道Nettle在玩《艦これ》。经过了一番苦战之后。Nettle又获得了的非常多非常多的船。

这一天Nettle在检查自己的舰队列表:



我们能够看到。船默认排序是以等级为參数。但实际上一个船的火力值和等级的关系并不大,所以会存在A船比B船等级高,可是A船火力却低于B船这种情况。比方上图中77级的飞龙改二火力就小于55级的夕立改二。

如今Nettle将依照等级高低的顺序给出全部船的火力值,请你计算出一共同拥有多少对船满足上面提到的这样的情况。

提示:火力高才是猛!

输入

第1行:1个整数N。N表示舰船数量, 1≤N≤100,000

第2行:N个整数。第i个数表示等级第i低的船的火力值a[i],1≤a[i]≤2^31-1。

输出

第1行:一个整数。表示有多少对船满足“A船比B船等级高,可是A船火力低于B船”。

例子输入
  1. 10
  2. 1559614248 709366232 500801802 128741032 1669935692 1993231896 369000208 381379206 962247088 237855491
例子输出
  1. 27

二.解题技巧

    依据题目的提示,这道题能够使用二分归并排序来对数组进行排序的同一时候,统计逆序数的个数。

详细做法是将两个子问题进行二分归并排序后得到的逆序数加上将子问题进行归并的时候。后面一半的元素移动的位置来得到终于的逆序数。



三.实现代码

#include <iostream>



#include <vector>



using namespace std;



long long Merge(vector<int>::iterator BeginIte, int Number)

{

    if (Number < 2)

    {

        return 0;

    }



    int Mid = Number / 2;



    int IndexFirst = 0;

    int IndexSecond = Mid;



    vector<int> TmpArray;

    long long Count = 0;

    int Index = 0;

    while ((IndexFirst < Mid) && (IndexSecond < Number))

    {

        int TmpFirst = *(BeginIte + IndexFirst);

        int TmpSecond = *(BeginIte + IndexSecond);



        if (TmpFirst > TmpSecond)

        {

            TmpArray.push_back(TmpSecond);

            Count += IndexSecond++ - Index++;

        }

        else

        {

            TmpArray.push_back(TmpFirst);

            IndexFirst++;

            Index++;

        }

    }



    while (IndexFirst < Mid)

    {

        TmpArray.push_back(*(BeginIte + IndexFirst++));

    }



    while (IndexSecond < Number)

    {

        TmpArray.push_back(*(BeginIte + IndexSecond++));

    }



     // copy the array back

    for (int Index = 0; Index < Number; Index++)

    {

        *(BeginIte++) = TmpArray[Index];

    }



    return Count;



}





long long MergeSort(vector<int>::iterator BeginIte, int Number)

{

    if (Number < 2)

    {

        return 0;

    }



    int Mid = Number / 2;

    long long Count = 0;

    Count += MergeSort(BeginIte, Mid);

    Count += MergeSort(BeginIte + Mid, Number - Mid);

    Count += Merge(BeginIte, Number);



    return Count;



}





int main()

{

    int Number = 0;

    cin >> Number;



    int Index = 0;

    vector<int> Array;

    while (Index++ < Number)

    {

        int Tmp = 0;

        cin >> Tmp;

        Array.push_back(Tmp);

    }



    cout << MergeSort(Array.begin(), Number) << endl;



//    for (int Index = 0; Index < Number; Index++)

//    {

//        cout << Array[Index] << endl;

//    }



    // cout << "The result is " << Count << endl;







    return 0;

}


四.体会

    这道题让我长了见识,我记得我曾经的做法是先使用STL里面的sort函数对数组进行排序,然后依据排序后的数组的元素的下标与同样元素在原来数组里面的下标的关系。来计算逆序对的个数(也就是逆序数)。

这样的方法不仅须要进行排序的时间O(nlgn),在使用hash_table的时候,还须要O(n)的时间来推断元素在排序后的数组的下标与原来数组的下标的关系,略微有些复杂。

    这道题使用二分归并排序在进行排序的同一时候,也递归计算量数组中的逆序对的个数。是一种非常有用的方法。

这样的方法主要是基于数组中的逆序对的个数等于子问题中存在的逆序对的个数加上归并过程中存在的逆序对的个数。归并过程中存在的逆序对的个数等于后面一半的元素移动到正确位置时须要移动的位数的和。





版权全部。欢迎转载,转载请注明出处,谢谢


hihoCoder_二分&#183;归并排序之逆序对的更多相关文章

  1. 归并排序+归并排序求逆序对(例题P1908)

    归并排序(merge sort) 顾名思义,这是一种排序算法,时间复杂度为O(nlogn),时间复杂度上和快排一样 归并排序是分治思想的应用,我们先将n个数不断地二分,最后得到n个长度为1的区间,显然 ...

  2. 归并排序求逆序对(poj 2299)

    归并排序求逆序对 题目大意 给你多个序列,让你求出每个序列中逆序对的数量. 输入:每组数据以一个数 n 开头,以下n行,每行一个数字,代表这个序列: 输出:对于输出对应该组数据的逆序对的数量: 顺便在 ...

  3. 2014 HDU多校弟五场A题 【归并排序求逆序对】

    这题是2Y,第一次WA贡献给了没有long long 的答案QAQ 题意不难理解,解题方法不难. 先用归并排序求出原串中逆序对的个数然后拿来减去k即可,如果答案小于0,则取0 学习了归并排序求逆序对的 ...

  4. 归并排序&&归并排序求逆序对

    归并排序 归并排序(MERGE-SORT)是建立在归并操作上的一种有效的排序算法,该算法是采用分治法(Divide and Conquer)的一个非常典型的应用.将已有序的子序列合并,得到完全有序的序 ...

  5. 【BZOJ4769】超级贞鱼 归并排序求逆序对

    [BZOJ4769]超级贞鱼 Description 马达加斯加贞鱼是一种神奇的双脚贞鱼,它们把自己的智慧写在脚上——每只贞鱼的左脚和右脚上各有一个数.有一天,K只贞鱼兴致来潮,排成一列,从左到右第i ...

  6. POJ-排序-归并排序与逆序对

    排序:归并排序与逆序对 一.概念 归并排序(MERGE-SORT)是建立在归并操作上的一种有效的排序算法,该算法是采用分治法(Divide and Conquer)的一个非常典型的应用.将已有序的子序 ...

  7. poj2299(归并排序求逆序对)

    题目链接:https://vjudge.net/problem/POJ-2299 题意:给定一个序列,每次只能交换邻近的两个元素,问要交换多少次才能使序列按升序排列. 思路:本质就是求逆序对.我们用归 ...

  8. 【hihocoder】三十九周:二分.归并排序之逆序对

    就是用归并排序求数组中得逆序对.假设数组为a:[2 4 5],和b:[1 3],那么在这一次归并的时候逆序对这样求,belement表示当前result数组中b数组对应的元素个数,total表示逆序对 ...

  9. <泛> 归并排序 及 逆序对

    今天写一个归并排序的模板,返回值为该序列的逆序对数 基本思路 归并排序就是利用二分的思想,将区间无限递归二分,直到当前划分区间只包含一个元素或没有元素的时候(我们认为这个序列是自动有序的),我们回溯到 ...

随机推荐

  1. HashMap面试题:90%的人回答不上来

    在java面试中集合类似乎已经是绕不开的话题,对于一个中高级java程序员来说如果对集合类的内部原理不了解,基本上面试都会被pass掉.下面从面试官的角度来聊聊一个候选者应该对HashMap了解到什么 ...

  2. 前端基于react,后端基于.net core2.0的开发之路(1) 介绍

    文章提纲目录 1.前端基于react,后端基于.net core2.0的开发之路(1) 介绍 2.前端基于react,后端基于.net core2.0的开发之路(2) 开发环境的配置,注意事项,后端数 ...

  3. mapbox-gl 开发包dev生成

    mapbox-gl简介 mapbox-gl采用webgl,提供在线地图实时渲染功能,具有以下特点: 1.多图层显示 2.图层元素显示样式在颜色.字体.大小范围等.是否显示等可实时更改 3.定位抓取选择 ...

  4. js同时使用多个分隔符分割字符串.

    利用正则分割,str.split(/reg/);如果有这样一个字符串: "jb51.net,google.com,baidu.com_weibo.com_haotu.net", 我 ...

  5. python视频教程全集

    由于Python语言的简洁.易读以及可扩展性,在国外用Python做科学计算的研究机构日益增多,一些知名大学已经用它来教授程序设计课程.如果你想找python视频教程全集,来这就对了!这是链接: py ...

  6. linux C/C++开发环境搭建指南

    一.安装基本开发环境 1.配置GCC 刚装好的系统中已经有GCC了,但是这个GCC什么文件都不能编译,因为没有一些必须的头文件,所以要安装build-essential这个软件包,安装了这个包会自动安 ...

  7. git打包

    git help tag #tag的用法git taggit tag -d xxx #删除taggit tag v1.1 #新增taggit describe --tag #  

  8. 基础拾遗----RabbitMQ(含封装类库源码)

    基础拾遗 基础拾遗------特性详解 基础拾遗------webservice详解 基础拾遗------redis详解 基础拾遗------反射详解 基础拾遗------委托详解 基础拾遗----- ...

  9. Python基础-数据类型和变量

    数据类型 python中包含6种标准数据类型:1.Number 数值类型2.String 字符串类型3.List 列表类型4.Tuple 元祖类型5.Dict 字典类型6.Set 集合类型 注意:除了 ...

  10. 《java.util.concurrent 包源码阅读》09 线程池系列之介绍篇

    concurrent包中Executor接口的主要类的关系图如下: Executor接口非常单一,就是执行一个Runnable的命令. public interface Executor { void ...