一.题目

题目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船”。

例子输入
10
1559614248 709366232 500801802 128741032 1669935692 1993231896 369000208 381379206 962247088 237855491
例子输出
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. JAVAscript学习笔记 jsBOM 第七节 (原创) 参考js使用表

    <html> <head> <title>day02_js</title> <script type="text/javascript& ...

  2. Python爬虫小实践:寻找失踪人口,爬取失踪儿童信息并写成csv文件,方便存入数据库

    前两天有人私信我,让我爬这个网站,http://bbs.baobeihuijia.com/forum-191-1.html上的失踪儿童信息,准备根据失踪儿童的失踪时的地理位置来更好的寻找失踪儿童,这种 ...

  3. ldap数据库--ODSEE--卸载

    针对ldap实例的卸载,即删除,可以通过管理界面进行操作也可以通过命令行进行操作.卸载顺序为ldap实例--agent--ads.这里主要介绍命令操作步骤 1,ldap实例卸载 从ads注销,即不在需 ...

  4. selenim之ActionChains(一)

    大家好,来介绍下,今天要分享的是小编学ActionChains的经验. 先来说一下今天要用到的方法: click(element=null)                               ...

  5. Vue Elementui 如何让输入框每次自动聚焦

    在项目优化中碰到一个小问题,在每次提示框显示的时候让提示框中的输入框聚焦.如下图.一般情况下提示框是隐藏的.点击了编辑才会弹出. 那么原生属性autofocus 只在模板加载完成时起作用,也就是说只有 ...

  6. .net core 开发短网址平台的思路

    最近有个客户要求开发一套短网址网站,小编现在都使用.net core进行网站开发了,以是厘厘思路,想想使用.net core 的中间件应该很容易实现. 1. 构建一个中间件,监测网站的响应状态,代码如 ...

  7. pattern

    A compiled representation of a regular expression. A regular expression, specified as a string, must ...

  8. 转载:Allegro实用技巧之模块复用

    http://bbs.ednchina.com/BLOG_ARTICLE_3031842.HTM?click_from=8800032437,9950148743,2016-01-04,EDNCOL, ...

  9. robotframework自动化系列:删除操作流程以及总结

    之前已经完成了登录.新增和修改的操作流程,这一节主要说明删除操作流程以及自动化的过程中出现的问题,算是对这个项目自动化的一个总结. 删除操作流程 对于系统账号管理中删除功能,删除的测试点主要如图所示 ...

  10. Spring AMQP + Rabbit 配置多数据源消息队列

    一般在稍微大一点的项目中,需要配置多个数据库数据源,最简单的方式是用 Spring 来实现,只需要继承 AbstractRoutingDataSource 类,实现 determineCurrentL ...