一.题目

题目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. ⒂bootstrap组件 折叠 基础案例

    <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...

  2. DataProtection Key的选择

    代码位于: Microsoft.AspNetCore.DataProtection.KeyManagement.DefaultKeyResolver.cs private IKey FindDefau ...

  3. 利用Python循环(包括while&for)各种打印九九乘法表

    一.for循环打印九九乘法表 #注意:由于缩进在浏览器不好控制,请大家见谅,后续会有图片传入. 1.1 左下角 for i in range(1,10): for j in range(1,i+1): ...

  4. Java反射机制使用场景

    import java.io.*; import java.util.Properties; /*问题描述:存在一个主板--已经定义好,不想修改其代码,还想在主板上面增加一些其他功能? *问题解决方法 ...

  5. MSSQL 常用操作

    0.GUID去除横线和变换为小写 SELECT LOWER(REPLACE(LTRIM(NEWID()),'-','')) 1.IDENTITY 函数说明 IDENTITY ( data_type [ ...

  6. 基于Jquery UI的autocompelet改写,自动补全控件,增加下拉选项,动态设置样式,点击显示所有选项,并兼容ie6+

    Jquery UI的autocompelete改写 注意:实现功能,除了原版的自动补全内容外,增加一个点击显示所有选项,样式能动态设置. 加载数据的来源为后台数据库读取. 具体代码如下: 引用 从官方 ...

  7. a标签嵌套解决方案

    在实际网页布局之中,我们有时候需要一整块点击区域中间还要有部分按钮点击,也就是需要a标签嵌套a标签,如下: <!-- a标签进行嵌套的时候 --><a href="#hao ...

  8. unity3d资源打包总结

    http://www.manew.com/blog-33734-12973.html unity 打包的时候会把下面几个文件资源打进apk或者ipa包里面 1. Asset下的所有脚本文件 2. As ...

  9. 分布式缓存之Ehcache与terracotta - Terracotta服务器概念篇

    1.介绍 Terracotta服务器为Terracotta产品提供分布式数据平台.Terracotta服务器集群被称为Terracotta服务器阵列(TSA).Terracotta服务器阵列可以从单个 ...

  10. 大数据基础篇(一):联机分析处理(OLAP) 与 联机事务处理(OLTP)

    联机事务处理(OLTP) OLTP也称实时系统(Real Time System),支持事务快速响应和大并发,这类系统典型的有ATM机(Automated Teller Machine)系统.自动售票 ...