逆序对的两种算法【树状数组 / 归并排序】

AI权益加码!Claude Code、Cursor等20+工具免费用! 购周边限时加赠Coding Plan Lite,畅享主流AI工具!学习进阶更高效! 阅读详情
  • 对于数组A[1…n],求逆序对对数。
  • 可根据数据范围离散化。
  • 以下算法时间复杂度:O(n * log n)。
  • 逆序对对数最大为n*(n-1)/2,结果经常要用long long保存。

树状数组算法

  1. 逐一读入a[i]。
  2. 利用树状数组统计比a[i]小的数个数s,逆序对个数加上i - 1 - s。
  3. 把a[i]计入树状数组,即结点i加1。
  4. 代码:
#include<bits/stdc++.h>
 using namespace std;

 const int MN = 1005;//MN根据数据决定 
 int n, i, x, ans, c[MN];

 inline int lowbit(int x)
 {
    return x & (-x);
 }

 inline int sum(int x)
 {
    int s = 0;
    for(; x; x -= lowbit(x)) s += c[x];
    return s;
 }

 inline void add(int x)
 {
    for(; x < n; x += lowbit(x)) c[x] ++;
 }

 int main()
 {

    scanf("%d", &n);

    memset(c, 0, sizeof(c));
    for(i = 1, s = 0; i <= n; ++ i)
    {
        scanf("%d", &x);
        ans += i - 1 - sum(x);
        add(x);
    }

    printf("%d", ans);

    return 0;

 }

归并排序算法

  1. 二分时,将数组a[l, r]分为a[l, mid]与a[mid + 1, r](mid = (l + r) >> 1)分别归并排序。
  2. 合并时,对于l <= i <= mid, mid + 1 <= j <= r,若a[i] > a[j],则a[i, mid]都比a[j]大,逆序对对数加上mid - i + 1。
  3. 代码:
#include<bits/stdc++.h>
 using namespace std;

 const int MN = 1005;//MN根据数据决定 
 int n, i, a[MN], b[MN], ans;

 inline void merge(int l, int r)
 {
    int mid = (l + r) >> 1, i, j, k;

    for(i = k = l, j = mid + 1; i <= mid && j <= r;)
    if (a[i] > a[j]) b[k ++] = a[j ++], ans += mid - i + 1;
    else b[k ++] = a[i ++];
    for(; i <= mid; i ++) b[k ++] = a[i];
    for(; j <= r; j ++) b[k ++] = a[j];

    for(i = l; i <= r; i ++) a[i] = b[i];
 }

 inline 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);
    merge(l, r);
 }

 int main()
 {

    scanf("%d", &n);

    for(i = 1, s = 0; i <= n; ++ i) scanf("%d", &a[i]);

    ans = 0;
    merge_sort(1, n);

    printf("%d", ans);

    return 0;

 }
算法篇:逆序对 逆序对的计算 阅读详情

相关推荐

逆序对问题的两种解思路(归并排序树状数组

本文讲解了逆序对问题的两种标准解方法

Lee贤的博客 3312

逆序对的三种方法

qq_52639492的博客 1万+

E - Inversion-归并排序逆序对/树状数组逆序对

...其实我知道要用归并排个序找个找到逆序对总数-k就好了,但是我当时以为自己想到了另一个算逆序对的方法,以为这是正确的。。所以才没用归并排序,,后面就一直调,忘了用归并。。。。整个人都不好了 http://acm.hust.edu.cn/vjudge/problem/viewProblem.action?id=52584 + #include #include #inc

缺氧 674

逆序对的各种算法

文章目录1.冒泡排序思想代码:2.归并排序思想代码3.树状数组思想代码线段树思想 设AAA为一个有nnn个数字的有序集(n>1)(n>1)(n>1),其中所有数字各不相同。 如果存在正整数i,ji,ji,j使得1≤i<j≤n1 ≤ i < j ≤ n1≤i<j≤n而且A[i]>A[j]A[i] > A[j]A[i]>A[j],则<A[i],A[j]><A[i], A[j]><A[i],A[j]>这个有序对称为AAA的一

sxhlrLX的博客 2306

逆序对的几种

逆序对的定义 设有一个序列,对于序列中任意两个元素ai,aj,若i&lt;j,ai&gt;aj,则说明aiaj是一对逆序对逆序对的几种法 1.暴力比较: 写两层循环,时间复杂度为 2.归并排序: 众所周知,归并排序就是将一个序列分成两部分进行排序,然后将排序后的两个序列中的元素一个一个插入(如图) 然后,我们发现,对于两个个正在排列的子序列,若后面的子序列中要插入元素,比...

juruo_hejiarui的博客 3万+

逆序对的三种

《 大 材 小 用 》

q779的博客 3221

洛谷 P1908 逆序对 题解 归并排序/树状数组/线段树

归并排序 树状数组 线段树 洛谷题解 C++代码 附注释

一只摸鱼的bbc 1388

逆序对归并排序+树状数组

题目描述 猫猫 TOM 小老鼠 JERRY 最近又较量上了,但是毕竟都是成年人,他们已经不喜欢再玩那种你追我赶的游戏,现在他们喜欢玩统计。 最近,TOM 老猫查阅到一个人类称之为“逆序对”的东西,这东西是这样定义的:对于给定的一段正整数序列,逆序对就是序列中a_i>a_j且i<j的有序对。知道这概念后,他们就比赛谁先算出给定的一段正整数序列中逆序对的数目。注意序列中可能有重复数字。 输入格式 第一行,一个数n,表示序列中有n个数。 第二行n个数,表示给定的序列。序列中每个...

Lineng's blog 1595

两种方法逆序对的数目

什么是逆序对 给一个序列:3 2 1 5 4 ,其中(3,2),(3,1),(2,1),(5,4)就叫做逆序对,下面将介绍两种逆序对的方法,一种是利用树状数组,也叫线段树的方法来逆序对的数目,另一种是利归并排序的思想来就逆序对的数目,通过逆序对的数目我们可以知道一个数组利用冒泡排序的思想可以在几步之内完成. 利用树状数组逆序对的个数 什么是树状数组 关于树状数组的介绍可以参考博客小白都能看懂...

twn29004的博客 4014

逆序对归并排序 / 树状数组

逆序对: 对于给定的一段正整数序列,逆序对就是序列中 ai > aj 且 i < j 的有序对。 (逆序数的法至少有三种:枚举法、分治法、树状数组。下面说说分治法。。。) 树状数组的做法以及离散化等内容见洛谷题解:P1908 逆序对 题解 归并排序解法(分治法): 归并排序(merge sort)是建立在归并操作上的一种有效的排序算法。 该算法是采用分治法(Divide and C...

道阻且长,行则将至 788

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

我们知道,逆序对最典型的方法就是树状数组,但是还有一种方法就是Merge_sort(),即归并排序。 实际上归并排序的交换次数就是这个数组的逆序对个数,为什么呢? 我们可以这样考虑: 归并排序是将数列a[l,h]分成两半a[l,mid]a[mid+1,h]分别进行归并排序,然后再将这两半合并起来。 在合并的过程中(设la[j]时,在

ACM_10000h的专栏 3685

算法逆序对

现在比较3、2,发现 3 > 2,所以把 2 放到合并后的数组,由于左半部分是有序的,所以 2 小于左半部分剩下的所有数,但 2 又在左半边剩下的所有数后面,所以 2 这些数都构成逆序对逆序对的数量就是。每一次右半部分的第一个数小于左半部分的第一个数时,右半部分的第一个数左半部分剩下的所有数都构成逆序对,因此在原来的基础上加上。的前缀,我们就可以得到在 x 前输出,比 x 的值小的元素个数,用总共输入的元素个数它相减,就可以得到。树状数组的原理在这里就不多说啦,如果有不懂的同学可以去看看。

Texcavator的博客 2132

归并排序逆序对算法思维的双重奏

本文深入探讨了归并排序逆序对问题的内在联系,展示了分治算法在信息学奥赛编程面试中的经典应用。通过详细解析归并排序的实现及其在逆序对统计中的优化应用,帮助读者掌握高效算法设计思维,提升解决复杂问题的能力。

w8x9y0z1的博客 942

逆序对两种解法

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

scwMason的博客 1089

逆序对问题、树状数组与离散化

本文主要讲了逆序对问题、归并排序法、树状数组与离散化处理,并讨论了一道例题。

m0_52711790的博客 1672

树状数组归并算法逆序对

引入 什么是逆序对? 概念:对于一对数字ai,ajai, ajai,aj,当i&lt;ji&lt;ji<j且ai&gt;ajai&gt;ajai>aj时,称这一对数字为逆序对。 对于逆序对而言,一般是有两种不同的解决方法,其一是树状数组,其二是归并排序。(我个人比较倾向于树状数组,毕竟是很早以前就学过了的算法,现在复习一遍印象深刻,但是归并就学的太早了...

Z 350

树状数组】【归并排序逆序对

逆序对的定义 在一个序列中,若存在i < j,a[i] > a[j],那么a[i] a[j]就是一对逆序对 归并排序逆序对 归并排序简单来说就是每次把序列二分,然后合并两个有序序列 在合并两个有序序列的过程中,可以用两个指针i,j分别对两个序列进行扫描,每次将a[i] a[j]中较小的那一个放到临时数组中 若a[j] < a[i],因为两个序列都是有序序列,那么a...

qq_43398760的博客 241

树状数组逆序对/ 兼板子 (有无重复数字都可)

归并排序树状数组都可以用nlogn的算法做到逆序对.但这里着重讲树状数组的原理与法. 树状数组最常用的方面就是用来逆序对, 普通方法需要n^2的复杂度, 而树状数组只需要用nlogn的复杂度, 所以是很好的优化, 关键在于内部函数lowbit的应用. 这是树状数组的结构图 : lowbit函数就是进行哪些实现之间的转化的, 因为这些数之间在二进制中存在着某种联系, 而lowbit函数...

Anxdada -- 我等风来也等你 1546

树状数组逆序对

树状数组逆序对题意思路算法思路 题意 给定一个长度为n的整数数列,请你计算数列中的逆序对的数量。 逆序对的定义如下:对于数列的第 i 个第 j 个元素,如果满足 i < j 且 a[i] > a[j],则其为一个逆序对;否则不是。 输入格式 第一行包含整数n,表示数列的长度。 第二行包含 n 个整数,表示整个数列。 输出格式 输出一个整数,表示逆序对的个数。 数据范围 1≤n≤1000001≤n≤100000 输入样例: 6 2 3 4 5 6 1 输出样例: 5 思路 经典逆序对问题,

离开那天的博客 819
上一篇: 树状数组(二叉索引树)
下一篇: 【逆序对】【cofun1917】奇数码问题
MYBHB_mio
博客等级 码龄9年 2粉丝 26原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值