NC15163 逆序数
NC15163 逆序数
题目
题目描述
在一个排列中,如果一对数的前后位置与大小顺序相反,即前面的数大于后面的数,那么它们就称为一个逆序。一个排列中逆序的总数就称为这个排列的逆序数。比如一个序列为 \(4\) \(5\) \(1\) \(3\) \(2\), 那么这个序列的逆序数为 \(7\),逆序对分别为 (4, 1), (4, 3), (4, 2), (5, 1), (5, 3), (5, 2),(3, 2) 。
输入描述
第一行有一个整数 \(n(1 <= n <= 100000)\) , 然后第二行跟着 \(n\) 个整数,对于第 \(i\) 个数 \(a[i],(0 <= a[i] <= 100000)\) 。
输出描述
输出这个序列中的逆序数
示例1
输入
5
4 5 1 3 2
输出
7
题解
思路
知识点:递归,排序。
众所周知,排序可以理解为把一个具有逆序数的序列变换为逆序数为零的序列。而归并排序每次交换元素,只会导致逆序数减少,而且可以非常容易的计算。
归并排序先把序列对半分,直到只有一个元素(可视为排序好的)开始回溯进行排序。而将两个排序好的序列归并是很容易的,只要用两个指针 \(i,j\) 分别指向两个数组的头部开始遍历,再创建一个临时数组,依次哪个小就放哪个进临时数组,最后覆盖回去即可。在这个过程中,各自序列的元素的相对位置不会改变,而左序列元素和右序列各个元素的相对位置可能会发生改变。每次遇到一个左序列元素大于右序列元素,则将右序列元素提前,仅在这个过程会仅减少逆序数,值为 \(mid-i+1\) ,即左序列剩余元素个数。将每次归并减少的逆序数累加,就是最终答案。
时间复杂度 \(O(n \log n)\)
空间复杂度 \(O(n)\)
代码
#include <bits/stdc++.h>
using namespace std;
long long cnt = 0;
int a[100007], b[100007];
void merge_sort(int l, int r) {
if (l == r) return;
int mid = l + r >> 1;
merge_sort(l, mid);
merge_sort(mid + 1, r);
int i = l, j = mid + 1, k = l;
while (i <= mid && j <= r) {
if (a[i] <= a[j]) b[k++] = a[i++];
else b[k++] = a[j++], cnt += mid - i + 1;
}
while (i <= mid) b[k++] = a[i++];
while (j <= r) b[k++] = a[j++];
for (int i = l;i <= r;i++) a[i] = b[i];
}
int main() {
std::ios::sync_with_stdio(0), cin.tie(0), cout.tie(0);
int n;
cin >> n;
for (int i = 0;i < n;i++) cin >> a[i];
merge_sort(0, n - 1);
cout << cnt << '\n';
return 0;
}
NC15163 逆序数的更多相关文章
- HDU3465 树状数组逆序数
Life is a Line Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 131072/65536 K (Java/Others)T ...
- HDU 1394 Minimum Inversion Number(最小逆序数 线段树)
Minimum Inversion Number [题目链接]Minimum Inversion Number [题目类型]最小逆序数 线段树 &题意: 求一个数列经过n次变换得到的数列其中的 ...
- 递归O(NlgN)求解逆序数
导言 第一次了解到逆序数是在高等代数课程上.当时想计算一个数列的逆序数直觉就是用两重循环O(n^2)暴力求解.现在渐渐对归并算法有了一定的认识,因此决定自己用C++代码小试牛刀. 逆序数简介 由自然数 ...
- FZU 2184 逆序数还原
传送门 Description 有一段时间Eric对逆序数充满了兴趣,于是他开始求解许多数列的逆序数(对于由1...n构成的一种排列数组a,逆序数即为满足i<j,ai>aj的数字对数),但 ...
- HDU 1394 Minimum Inversion Number(最小逆序数/暴力 线段树 树状数组 归并排序)
题目链接: 传送门 Minimum Inversion Number Time Limit: 1000MS Memory Limit: 32768 K Description The inve ...
- poj 1007:DNA Sorting(水题,字符串逆序数排序)
DNA Sorting Time Limit: 1000MS Memory Limit: 10000K Total Submissions: 80832 Accepted: 32533 Des ...
- POJ 2299 Ultra-QuickSort 逆序数 树状数组 归并排序 线段树
题目链接:http://poj.org/problem?id=2299 求逆序数的经典题,求逆序数可用树状数组,归并排序,线段树求解,本文给出树状数组,归并排序,线段树的解法. 归并排序: #incl ...
- HDU 4911 (树状数组+逆序数)
题目链接: http://acm.hdu.edu.cn/showproblem.php?pid=4911 题目大意:最多可以交换K次,就最小逆序对数 解题思路: 逆序数定理,当逆序对数大于0时,若ak ...
- HDU-Minimum Inversion Number(最小逆序数)
Problem Description The inversion number of a given number sequence a1, a2, ..., an is the number of ...
随机推荐
- kubeadm 搭建 K8s
kubeadm 搭建 K8s 本篇主要记录一下 使用 kubeadm 搭建 k8s 详细过程 ,环境使用 VirtualBox 构建的3台虚拟机 1.环境准备 操作系统:Centos7 (CentOS ...
- 为何PostgreSQL即将超越SQL Server?
DB-Engines 2021年10月份统计,PostgreSQL当月上升10.30点,总分是597.27:SQLServer当月大幅下降16.32,总分是954.29 .按照这样的速度,2年之内,P ...
- Kafka生成消息时的3种分区策略
摘要:KafkaProducer在发送消息的时候,需要指定发送到哪个分区, 那么这个分区策略都有哪些呢? 本文分享自华为云社区<Kafka生产者3中分区分配策略>,作者:石臻臻的杂货铺. ...
- Jenkins Build step 'Execute shell' marked build as failure
问题出现: Jenkins一直都构建成功,今天突然报错:Jenkins Build step 'Execute shell' marked build as failure 问题原因: By defa ...
- GO语言学习——切片三 append()方法为切片添加元素、切片的扩容策略、使用copy()函数复制切片、从切片中删除元素
append()方法为切片添加元素 注意:通过var声明的零值切片可以在append()函数直接使用,无需初始化. var s []int s = append(s, 1, 2, 3) append( ...
- Java — 面向对象
目录 一.类和对象 二.方法 三.封装 四.继承 五.多态 六.final 七.static 八.抽象类 九.接口 十.内部类 一.类和对象 简介:类是对事物的一种描述,对象则为具体存在的事物. 类的 ...
- 前端HTML-01
HTML是什么? 超文本标记语言,是一种用于创建网页的标记语言 文件的扩展名:.html或者.htm HTML不是什么? HTML是一种标记语言,不是变成语言. HTML文档结构 <!DOCTY ...
- flask配置文件、路由设置、模板语法、请求与响应、session使用、闪现功能(flash)
今日内容概要 flask 配置文件 flask 路由系统 flask模板语法 请求与相应 session 闪现(flash翻译过来的) 内容详细 1.flask 配置文件 # django ---&g ...
- C++面向对象-类和对象那些你不知道的细节原理
一.类和对象.this指针 OOP语言的四大特征是什么? 抽象 封装.隐藏 继承 多态 类体内实现的方法会自动处理为inline函数. 类对象的内存大小之和成员变量有关 类在内存上需要对齐,是为了减轻 ...
- Linux磁盘空间查看及空间满的处理
问题 在部署应用到测试环境的时候,有些文件同步出错,最后定位到测试服务器空间满了. 解决 查看磁盘空间还剩多少空间 df -h 查看根目录下每个目录占用空间大小 du --max-depth=1 -h ...