POJ2299 求逆序对总数 归并算法解决

逆序对 比如 3 2 1  

3之前的数没有比它大的(或者说前面没有数了),所以没有逆序对

2之前的数有3比它大 所以有逆序对+1

1之前的数有 3 2 比它大 所以有逆序对+2

所以 3 2 1 序列 的 总的逆序对为3对

-----

在归并算法中 合并两个已经排序好的序列时 是从两个序列的首个位置开始进行比较

合并方法传入的参数为:first mid(分界下标) last

第一个序列下标:first ~ mid

第二个序列下标:mid + 1 ~ last

1.如果a[i] <= a[j]  显然 不存在 逆序对

2.如果a[i]>a[j] 显然 存在逆序对,此时,既然a[i]>a[j] 那么i后面的下标(i+1~mid)对应的数a[i]也绝对大于a[j] 所以存在逆序对(mid - i + 1)(包括a[i]在内的数以及后面的数都大于a[j],逆序对就为mid-i+1对)

经过归并排序之后,累加的逆序对数就是整个序列的总的逆序对数 即 答案

【注意】

由于输入的序列长度最大为500000 且每个数可达到999999999,所以累加逆序对数的变量最好用long long数据类型

时间: 2024-10-08 05:42:41

POJ2299 求逆序对总数 归并算法解决的相关文章

hdoj 1394 Minimum Inversion Number【线段树求逆序对】

求逆序对有很多算法,这里说一下线段树求逆序对的思想. 知识点:线段树,逆序对,单点更新,成段求和 算法:线段树求逆序数的前提条件是要离散化,变成连续的点,首先建树,每个节点设置一个num值为0. 然后根据逆序对的定义,前面出现过的比当前数大的个数的和,我们需要求前面的比他大的数,其实就相当于从当前a[i]点对他后面所有出现过的数求和一次.然后把当前点的值在线段树叶子节点变为1,表示出现过,并向上更新到线段树里面.比如说样例4 2 1 5 3 首先4后面没有值,4更新为1,4--5区间更新为1,1

HDU 4911 Inversion(归并求逆序对)

HDU 4911 Inversion 题目链接 题意:给定一个数组,可以相邻交换最多k次,问交换后,逆序对为多少 思路:先利用归并排序求出逆序对,然后再减去k就是答案 代码: #include <stdio.h> #include <string.h> #include <algorithm> using namespace std; const int N = 100005; int n, num[N], save[N], sn; void init() { for

算法笔记_065:分治法求逆序对(Java)

目录 1 问题描述 2 解决方案 2.1 蛮力法 2.2 分治法(归并排序)   1 问题描述 给定一个随机数数组,求取这个数组中的逆序对总个数.要求时间效率尽可能高. 那么,何为逆序对? 引用自百度百科: 设 A 为一个有 n 个数字的有序集 (n>1),其中所有数字各不相同. 如果存在正整数 i, j 使得 1 ≤ i < j ≤ n 而且 A[i] > A[j],则 <A[i], A[j]> 这个有序对称为 A 的一个逆序对,也称作逆序数. 例如,数组(3,1,4,5,

归并法求逆序对

l例题连接:https://www.luogu.org/problem/P1908 猫猫TOM和小老鼠JERRY最近又较量上了,但是毕竟都是成年人,他们已经不喜欢再玩那种你追我赶的游戏,现在他们喜欢玩统计.最近,TOM老猫查阅到一个人类称之为“逆序对”的东西,这东西是这样定义的:对于给定的一段正整数序列,逆序对就是序列中ai>aj且i<j的有序对.知道这概念后,他们就比赛谁先算出给定的一段正整数序列中逆序对的数目.Update:数据已加强. 输入格式 第一行,一个数n,表示序列中有n个数. 第

poj2299(归并排序求逆序对)

题目链接:https://vjudge.net/problem/POJ-2299 题意:给定一个序列,每次只能交换邻近的两个元素,问要交换多少次才能使序列按升序排列. 思路:本质就是求逆序对.我们用归并排序求逆序对,这也是简单的cdq分治. #include<cstdio> #include<algorithm> #include<cstdlib> #include<cmath> using namespace std; typedef long long

求逆序对(线段树版)

一个序列a1,a2,a3...aN,求出满足:ai > aj 且 i < j 的个数. 一个最容易想到的方法就是枚举所有的i,j看看是否满足,显然是O(n^2)的复杂度.不够好. 可以这样考虑,开一个数组保存这n个数出现的位置和对应的次数,这个数组要开到a数组里最大的那个数MAX,也就是hash,初始状态数组里没有元素,每个数对应的个数都是0. 如果考虑第i个数,找到比它大的所有的数 的个数,查找的范围即 ai+1~MAX,这就是到i这个位置的逆序对的总和,接着把a[i]这个数添加到数组里,也

分治法求逆序对数目

设A[1..n]是一个包含n个不同整数的数组.如果在i<j的情况下,有A[i]>A[j],则(i,j)就称为A中的一个逆序对(inversion). 给出一个算法,确定n个元素的任何排列中逆序对的书目.时间复杂度为o(nlgn). 分治法求解思路: 分解:将数组A[1..n]分为两个子序列A[1..p]和A[p+1,n],二分法将其分解.. 解决:根据归并排序的思想,在合并过程中,计算逆序对.假如两个子序列为X={4,5}和Y={2,3},则XY的逆序对为X中元素大于Y中元素的数目. 合并:对

权值线段树求逆序对问题

我们都知道,求逆序对数量可以用归并排序解决.但是用归并排序只能解决静态的序列问题,没有扩展的区间.因此就有了用权值线段树求逆序对的方法. 1 #include<iostream> 2 #include<iomanip> 3 #include<ctime> 4 #include<climits> 5 #include<algorithm> 6 #include<queue> 7 #include<vector> 8 #inc

每日一题26:求逆序对数目与求和

求逆序对问题与解决方案原理 在一个数列中,如果规定从小到大为正序,那么如果排在后面的某个元素比前面的某一个元素小,那么就称这两个数构成一个逆序对,例如,数列5,4,3,2,1中,任一个数都与它前面的数构成逆序对,这个序列中一共就有1+2+3+4=10个逆序对,数列23541中有5个逆序对,那么任给定一个数列,如何知道有多少个逆序对呢?简单的方法是将每个元素与它后面的元素比较,然后就可以累加出总的逆序对数目,这种算法的复杂度是O(n^2).另一种比较快的方法是利用归并排序,得到的算法复杂度为O(n