题目地址
使用离散化和树状数组的代码

题目描述:

riba2534不小心穿越到了异世界,他必须从异世界出来,但是异世界有一个大魔王,非得让riba2534回答出他的问题才让他回到地球,问题是这样的:

大魔王用魔法变出来了n座大山,并且告诉你这n座大山的高度,现在他想问你,对于给出的每一座大山,这座大山之前有多少座大山比他的高度低。

riba2534非常惊慌失措,所以请你救救他!

输入描述:

多组测试数据 第一行给出一个整数n(1<=n<=100000)代表有n座大山
第二行给出来每座大山的高度h(1<=h<=1000000000),以空格作为分割。

输出描述:

对于每组数据,输出一行。 代表每座大山之前有多少座大山比这座大山低

思路

在这里就不介绍采用分治发的归并排序了,大家可以去这里看“点击”,刚开始做这题用了树状数组和离散化才把它A了,后来看了最优代码是用的是分治之后,打算写一篇采用分治的解法。(假定看这篇博客时各位已经掌握了归并排序)。
首先,由于排序后会改变它原先的位置(除了个别已经恰好排好了的),所以要记录他们原先在数组中的位置,也就是使用了一个结构体(由于只有两个信息,所以我使用了结构体模板pair)

const int N = 1e5+1;
pair<int , int>a[N], temp[N];
int num[N];
temp数组用于做中间变量,知道归并排序的都懂!
num数组储存结果

刚开始的时候我采用的是从小到大排序的算法,发现会有好多情况需要考虑,然后换成从大到小的方法就很容易理解了。
还是举个例子吧,来个理想化的
3 2 1 6 5 4
由于我们是按逆序排的,所以最后要合并的两个区间的是(3,2,1) 和(6,5,4)并且现在这两个区间内每个数的num值都为0,然后我们来进行合并操作。

void merga(int l, int mid, int r) {int i = l, j = mid + 1, k = l;while(i <= mid && j <= r) { if(a[i].first >= a[j].first) { //first是值, second是每个数最开始时的位置。temp[k++] = a[i++];} else { num[a[j].second] += mid + 1 - i;temp[k++] = a[j++];} } while(i <= mid) temp[k++] = a[i++];while(j <= r) temp[k++] = a[j++];for (int i = l; i <= r; i++) { a[i] = temp[i];}
}

我来模拟一下他增加的操作,
3 < 6, num[3] (6在原数组中下表为3,别搞混了) += 2 + 1 - 0
3 < 5, num[4] += 2 + 1 - 0;
3 < 4, num[5] += 2 + 1 - 0;
最后合并。
也就是说它现在就是在找左边有多少个比右边的小,为什么是+=呢,实际上也很简单,如果我们把我刚刚的例子当成是另一个更长的数组的子串,那么再进行合并的时候就得加上上一次合并的结果。
给出完整代码:

#include<iostream>
#include<cstring>
using namespace std;
const int N = 1e5+1;
pair<int , int>a[N], temp[N];
int num[N];
void merga(int l, int mid, int r) {int i = l, j = mid + 1, k = l;while(i <= mid && j <= r) { if(a[i].first >= a[j].first) { temp[k++] = a[i++];} else { num[a[j].second] += mid + 1 - i;temp[k++] = a[j++];} } while(i <= mid) temp[k++] = a[i++];while(j <= r) temp[k++] = a[j++];for (int i = l; i <= r; i++) { a[i] = temp[i];}
}
void merga_sort(int l, int r) { if(l < r) {int mid = (l + r) / 2;merga_sort(l, mid);merga_sort(mid + 1, r);merga(l, mid, r);}
}
int main() { ios::sync_with_stdio(false);cin.tie(0);int n;while(cin >> n) { memset(num, 0, sizeof(num));for (int i = 0; i < n; i++) { cin >> a[i].first;a[i].second = i;} merga_sort(0, n-1);for (int i = 0; i < n; i++) { cout << num[i];if(i < n - 1)cout << " ";else cout << endl;} }
}

萌新表达可以不太准确,有什么不懂的可以在下面评论。若有哪里不正确,请各位大佬指正。

1491-救救riba2534(归并排序,分治)相关推荐

  1. c语言分治算法之归并排序,分治算法之归并排序

    分治算法: 将一个规模为N的问题分解为K个规模较小的子问题,这些子问题互相独立且与原问题性质相同.求出子问题的解后进行合并,就可得到原问题的解. 一般步骤: 1.分解,将要解决的问题划分成若干规模较小 ...

  2. python选择排序算法图解_python基本算法之实现归并排序(Merge sort)

    0.前言 评判一个算法的好坏的标准: 时间复杂度 空间复杂度 1.归并排序算法是什么? 冒泡排序(Bubble Sort)是一种建立在归并操作上面的一种有效的排序算法,由John von neuman ...

  3. python 归并排序算法_python基本算法之实现归并排序(Merge sort)

    0.前言 评判一个算法的好坏的标准: 时间复杂度 空间复杂度 1.归并排序算法是什么? 冒泡排序(Bubble Sort)是一种建立在归并操作上面的一种有效的排序算法,由John von neuman ...

  4. 数据结构——归并排序

    1. 归并排序 分治模型在每层递归时都有三个步骤: 分解原问题为若干子问题,这些子问题是原问题的规模较小的实例: 解决这些子问题,递归地求解各子问题.然而,若子问题的规模足够小,则直接求解: 合并这些 ...

  5. 归并排序Java详解+例题

    归并排序->分治 归并排序 归并排序->分治 背景 归并原理与过程 原理: 过程 图形展示 模板代码 模板讲解 归并例子 完整java代码 背景 归并排序是十大排序之一 十大排序: 归并原 ...

  6. python实现基本算法之归并排序(Merge sort)

    基本算法之归并排序(Merge sort) 基本算法-04.归并排序(Merge sort)算法 .往期请看选择排序,插入排序,归并排序,快速排序等等都发布的!欢迎大家批评指正! 文章目录 基本算法之 ...

  7. 算法笔记--八个常见排序算法总结

    一. 分类描述 1. 插入排序 直接插入排序:算法简单,稳定,适用于数据量小的情况 希尔排序:直接插入排序的改进版,不稳定,对于待排序序列的不同情况效率相近 2. 交换排序 冒泡排序:算法简单,稳定, ...

  8. 《算法之道》精华 经典算法部分

    <算法之道>精华 经典算法部分 本书作者邹恒明,作者另有一本书<数据结构之弦>,以及<操作系统之哲学原理>都是非常好的书 这本书能够算得上是深入浅出,文笔非常好.作 ...

  9. 如何给100亿个数字排序

    转自:http://netsmell.com/post/how-sort-10-billion-data.html?ref=myread 海量数据处理/外部归并排序 - 分治.cppp 今天要给100 ...

最新文章

  1. LOJ#2302 整数
  2. 从0到1学C++ 第3篇 从结构到类的演变
  3. matplotlib - 3D scatter plot
  4. 掌握AI核心技术没有秘籍,能自己创造就是王道
  5. [运动][组合]睡前运动
  6. Dropout也能自动化了,谷歌Quoc Le等人利用强化学习自动找寻模型专用Dropout
  7. MySQL SQL 优化命令行问题 SQL 抓取方式
  8. erp核心目的及erp特点
  9. 剑指offer——复习1:二叉树三种遍历方式的迭代与递归实现
  10. 四阶龙格库塔算法及matlab代码
  11. Mybatis事务原理
  12. ps计算机内存不足请保存文件并关闭,保存技巧,如何解决PS内存不足无法存储的错误提示情况...
  13. 一键查询 | 2020年最新SCI期刊影响因子报告
  14. Selenium||解决给元素输入文本失败问题
  15. html组态插件_组态 web组态 组态插件 编辑器 工业组态 物联网组态 组态编辑器...
  16. linux中mv、cp、rm分别是什么意思
  17. 软件工程小组项目——网上书店
  18. 像素颜色和颜色向量相加相乘的理解
  19. VERO.VISI.v2016.R2-ISO 1DVD模具设计
  20. 几种概率分布(伯努利分布、二项分布、泊松分布、均匀分布、正态分布、指数分布、伽马分布)

热门文章

  1. X64dbg没有uac权限不能拖放打开文件的解决办法!
  2. 银河麒麟系统常见问题
  3. 两台银河麒麟系统共享网络上网分享
  4. 2015060907 - 为什么有的工程师早晨醒来头发成为沟壑,角色无所谓就去上班呢?
  5. 2021隆昌高考成绩查询,隆昌县第二中学2021年网站网址
  6. 主题网络爬虫研究综述
  7. vue @click 多次触发解决
  8. 电子书格式及其反编译思路
  9. 网站扫描(Wker_网站探测工具)
  10. PaperWeekly 第32期 | 基于知识图谱的问答系统关键技术研究 #01