归并法求逆序对

l例题连接:https://www.luogu.org/problem/P1908

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

输入格式

第一行,一个数n,表示序列中有n个数。

第二行n个数,表示给定的序列。序列中每个数字不超过10^9109

输出格式

给定序列中逆序对的数目。

输入输出样例

输入 #1复制

6
5 4 2 6 3 1

输出 #1复制

11

说明/提示

对于25%的数据,n \leq 2500n≤2500

对于50%的数据,n \leq 4 \times 10^4n≤4×104。

对于所有数据,n \leq 5 \times 10^5n≤5×105

请使用较快的输入输出

应该不会n方过50万吧 by chen_zhe

归并求逆序对例题

   #include<iostream>
using namespace std;
const int N=5e5+7;
typedef long long ll;
int arr[N];
//int a[N];
int right_[N];
//int r[N];
ll ans=0;
void merage_sort(int l,int r){
    if(l>=r) return ;
    int mid=(l+r)/2;
    merage_sort(l,mid);
    merage_sort(mid+1,r);
    int i=l,j=mid+1,k=l;
    while(i<=mid&&j<=r){
        if(arr[i]<=arr[j]){
            right_[k++]=arr[i++];
        }
        else {
            right_[k++]=arr[j++];
            ans+=1ll*mid-i+1;
        }
    }
    while(i<=mid)    right_[k++]=arr[i++];
    while(j<=r)   right_[k++]=arr[j++];
    for(int i=l;i<=r;i++)    arr[i]=right_[i];
}

int main(){
    int n;
    cin>>n;
    for(int i=1;i<=n;i++){
        cin>>arr[i];
    }
    merage_sort(1,n); 

    cout<<ans<<endl;
    return 0;
}

原文地址:https://www.cnblogs.com/Accepting/p/11407258.html

时间: 2024-11-02 13:34:04

归并法求逆序对的相关文章

笔试算法题(32):归并算法求逆序对 &amp; 将数组元素转换为数组中剩下的其他元素的乘积

出题:多人按照从低到高排成一个前后队列,如果前面的人比后面的高就认为是一个错误对: 例如:[176,178,180,170,171]中的错误对 为 <176,170>, <176,171>, <178,170>, <178,171>, < 180,170>, <180,171>. 现在要求从一个整数序列中找出所有这样的错误对: 分析: 逆序对(Inversion Pair):在N个可判断大小的数中,逆序对的数量为[0,n(n-1)/2

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

codevs 4163 求逆序对的数目 -树状数组法

4163 hzwer与逆序对 时间限制: 10 s 空间限制: 256000 KB 题目等级 : 黄金 Gold 题目描述 Description hzwer在研究逆序对. 对于数列{a},如果有序数对(I,j)满足:i<j,a[i]>a[j],则(i,j)是一对逆序对. 给定一个数列{a},求逆序对个数. 输入数据较大,请使用scanf代替cin读入. 输入描述 Input Description 第一行一个数n,表示{a}有n个元素. 接下来n个数,描述{a}. 输出描述 Output D

归并排序,树状数组 两种方法求逆序对

我们知道,求逆序对最典型的方法就是树状数组,可是另一种方法就是Merge_sort(),即归并排序. 实际上归并排序的交换次数就是这个数组的逆序对个数,为什么呢? 我们能够这样考虑: 归并排序是将数列a[l,h]分成两半a[l,mid]和a[mid+1,h]分别进行归并排序,然后再将这两半合并起来. 在合并的过程中(设l<=i<=mid,mid+1<=j<=h).当a[i]<=a[j]时.并不产生逆序数:当a[i]>a[j]时.在 前半部分中比a[i]大的数都比a[j]

算法笔记_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,

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

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

归并排序求逆序对 //(洛谷)U4566 赛车比赛

https://www.luogu.org/problem/show?pid=U4566 显然的逆序对,以前只是嘴巴ac,这次终于打了出来. 逆序对其实就是冒泡排序的排序次数....但是一般的排序时间复杂度为O(n^2),于是都会想到归并排序... 一.二路归并 已知两个有序数组,将其归并为一个有序数组 很显然,将首元素比较,小的扔进目的数组,最后把剩下的扔进去.. 1 int a[n],b[m],tmp[n+m]; 2 int i=1,j=1,k=1; 3 while(i<=n&&

求逆序对 36

? ? 引言 ? ? 一开始接触到这题还觉得挺有意思的,但后来发现其深层次的含义就是一个归并排序,只是在归并排序的过程中做了一点小动作而已,这也再次证明了很多东西都是万变不离其宗的 ? ? 本文首先讲了一下归并排序的过程,用了自己比较喜欢的简洁的方式,然后对比归并排序与求逆序对之间的关系,发现需要稍微修改一下合并两个已排序数组的方法,要从两个数组的最后的数开始 ? ? 最后考虑到如果求逆序对的字符是固定数目的话,比如4个,详情可以参考后面的,那么时间复杂度不用归并排序的nlogn了,如果我们可以

[树状数组]求逆序对

ci 的意思是在前lowbit 中元素的个数. 然后往前i个中的sum就是小于等于这个i的个数 这个数的位置-小于等于这个i的个数 就是前面大于这个数的个数 小于等于这个数的个数肯定比 这个数的位置要小. 1 #include<iostream> 2 #include<cstdio> 3 #include<cmath> 4 #include<string> 5 #include<cstring> 6 #include<queue> 7