一.题目

题目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. python利用django实现简单的登录和注册,并利用session实现了链接数据库

    利用session实现与数据库链接,登录模块(在views.py) def login(request): # return HttpResponseRedirect('/') # 判断是否post方 ...

  2. Java动手动脑——多态和继承

    Java动手动脑——继承和多态 实验一 预估输出答案:100  200  201  202 输出结果:100  200  201  202 输出答案分析:100 创建parent类的对象,调用对象的方 ...

  3. 学习RocketMQ (一) 安装并且启动MQ

    1.使用RocketMQ 的 软件要求 64bit OS, Linux/Unix/Mac is recommended;64bit JDK 1.8+;Maven 3.2.xGit 1)安装Linux ...

  4. hadoop的webUI查看Live Nodes为1

    开起了两个节点,而且jps查看确实开启了,但是用web端50070查看却一直显示为1 经过排查,将虚拟机直接copy一份,但是之前配置好hadoop环境的namenode格式化(format)生成的文 ...

  5. 关于thinkphp控制器引用model里的方法的一点收获

    有时候真的是很绕,为了这一点点收获,我几乎花了一天的时间.当我弄明白了的那一刻,我.........好吧,写到这里,我发现不能换行.好吧,就这样吧,开始说正题:要想在controler从model引用 ...

  6. UWP 返回顶部按钮

    返回顶部的按钮,like this 当用户下滑了一定的距离之后,通常是快滑倒底部的时候,出现返回顶部按钮,当用户向上快滑,滑到顶部的时候,返回顶部按钮自动消失. 在UWP中,用来滚动内容的控件是Scr ...

  7. tornado之Hello world

    #!/usr/bin/env python26 #-*- coding:utf8 -*- import tornado.httpserver import tornado.ioloop import ...

  8. crontab中使用python无法执行

    手动执行可以的,但是在crontab中却无法执行,在网上搜了一圈,给出的结论是将相对路径改成绝对路径. 改了之后解决这个问题. 是不是依赖某些环境变量,linux 里的 cron 只有几个基本的环境变 ...

  9. vim操作命令

    一,命令模式下 文件顶部: gg 文件底部: G 删除当前行:dd 删除当前行,并进入INSERT模式: cc 取消删除:u

  10. 书籍推荐系列之一 -- 《凤凰项目:一个IT运维的传奇故事》

    博客已经完全更新了名字,新的名字,新的开始,想让自走向新的道路是很难的,走出舒适圈说了好久,也是时候开始行动了,今天就从写博客开始. 今天给大家推荐一本书,<凤凰项目:一个IT运维的传奇故事&g ...