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

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

逆序对

题目描述

猫猫 TOM 和小老鼠 JERRY 最近又较量上了,但是毕竟都是成年人,他们已经不喜欢再玩那种你追我赶的游戏,现在他们喜欢玩统计。

最近,TOM 老猫查阅到一个人类称之为“逆序对”的东西,这东西是这样定义的:对于给定的一段正整数序列,逆序对就是序列中 a i > a j a_i>a_j ai​>aj​ 且 i < j i<j i<j 的有序对。知道这概念后,他们就比赛谁先算出给定的一段正整数序列中逆序对的数目。注意序列中可能有重复数字。

输入格式

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

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

输出格式

输出序列中逆序对的数目。

样例 #1

样例输入 #1

6
5 4 2 6 3 1

样例输出 #1

11

提示

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

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

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

请使用较快的输入输出。

原题

洛谷P1908——传送门

代码

解法一:归并排序

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;

const int maxn = 5e5 + 6;
ll a[maxn], tmp[maxn], n, ans = 0;
void mergeSort(ll l, ll r) // 归并排序
{
    if (l >= r)
        return;
    // 分治
    ll mid = (l + r) >> 1, i = l, j = mid + 1, cnt = 0;
    mergeSort(l, mid);
    mergeSort(mid + 1, r);
    while (i <= mid || j <= r)
        if (j > r || (i <= mid && a[i] <= a[j]))
            tmp[cnt++] = a[i++];
        else
            tmp[cnt++] = a[j++], ans += mid - i + 1; // 统计逆序对数量
    for (ll k = 0; k < r - l + 1; k++)
        a[l + k] = tmp[k];
}

int main()
{
    ios::sync_with_stdio(0);
    cin.tie(0);

    cin >> n;
    for (int i = 1; i <= n; i++)
    {
        cin >> a[i];
    }
    mergeSort(1, n);
    cout << ans << '\n';

    return 0;
}

解法二:树状数组

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;

const int maxn = 5e5 + 6;

int n;

int tr[maxn]; // 树状数组

int lowbit(int x) // 获取低位2次幂数
{
    return x & -x;
}

void update(int x, int k) // 单点add
{
    while (x <= n)
    {
        tr[x] += k;
        x += lowbit(x);
    }
}

int query(int x) // 前缀和查询
{
    int res = 0;
    while (x)
    {
        res += tr[x];
        x -= lowbit(x);
    }
    return res;
}

int ranks[maxn]; // 下标对应的数的大小排名

int main()
{
    ios::sync_with_stdio(0);
    cin.tie(0);

    cin >> n;
    vector<pair<int, int>> a(n + 1);
    for (int i = 1; i <= n; i++)
    {
        cin >> a[i].first;
        a[i].second = i;
    }
    sort(a.begin() + 1, a.end()); // 按数值为第一关键字,下标为第二关键字排序(这样的话重复数字也不会被统计进逆序对)
    for (int i = 1; i <= n; i++)
    {
        ranks[a[i].second] = i;
    }
    ll ans = 0;
    for (int i = 1; i <= n; i++)
    {
        update(ranks[i], 1);
        ans += i - query(ranks[i]); // query查询的是前缀和,逆序对需要用i-query即当前对总数减去非逆序对数量
    }
    cout << ans << '\n';

    return 0;
}

解法三:线段树

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;

const int maxn = 5e5 + 6;

int n;

#define lc p << 1
#define rc p << 1 | 1

int ranks[maxn]; // 下标对应的数的大小排名

struct node
{
    int l, r, sum;
} tr[maxn * 4];

void build(int p, int l, int r) // p是当前位置,l和r表示区间
{
    if (l == r)
    {
        tr[p] = {l, r, 0};
        return;
    }
    int mid = l + r >> 1;
    build(lc, l, mid);
    build(rc, mid + 1, r);
    tr[p] = {l, r, tr[lc].sum + tr[rc].sum};
}

void update(int p, int x, int k) // p是当前位置,update是对x位置上的数加k
{
    if (tr[p].l == x && tr[p].r == x) // 修改叶子节点
    {
        tr[p].sum += k;
        return;
    }
    // 更新非叶子节点的sum
    int mid = tr[p].l + tr[p].r >> 1;
    if (x <= mid)
        update(lc, x, k);
    else
        update(rc, x, k);
    tr[p].sum = tr[lc].sum + tr[rc].sum;
}

int query(int p, int x, int y) // p是当前位置,x和y表示区间
{
    if (x <= tr[p].l && tr[p].r <= y) // 已覆盖则返回该部分的结果
        return tr[p].sum;
    int mid = tr[p].l + tr[p].r >> 1;
    int sum = 0;
    if (x <= mid)
        sum += query(lc, x, y);
    if (y > mid)
        sum += query(rc, x, y);
    return sum;
}

int main()
{
    ios::sync_with_stdio(0);
    cin.tie(0);

    cin >> n;
    vector<pair<int, int>> a(n + 1);
    for (int i = 1; i <= n; i++)
    {
        cin >> a[i].first;
        a[i].second = i;
    }
    sort(a.begin() + 1, a.end()); // 按数值为第一关键字,下标为第二关键字排序
    for (int i = 1; i <= n; i++)
    {
        ranks[a[i].second] = i;
    }
    build(1, 1, n);
    ll ans = 0;
    for (int i = 1; i <= n; i++)
    {
        update(1, ranks[i], 1);
        ans += i - query(1, 1, ranks[i]);
    }
    cout << ans << '\n';

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

相关推荐

C:输入一个字符串,对该字符串进行逆序,输出逆序后的字符串。

题目描述: 输入一个字符串,对该字符串进行逆序,输出逆序后的字符串。 输入格式: 输入在一行中给出一个不超过80个字符长度的、以回车结束的非空字符串。 输出格式: 在一行中输出逆序后的字符串。 输入样例: Hello World! 输出样例: !dlroW olleH 题解: #include<string.h> int main(){ char a[81]; int i,j; gets(a); j=strlen(a); for(i=j-1;i>=0;i--) printf("

xiaolajiruirui的博客 2万+

P1908 逆序对 【归并排序】

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

ln2037的博客 791

零代码实战:基于Coze平台打造测试用例生成AI助手

本文详细介绍了如何利用Coze平台零代码打造测试用例生成AI助手,通过智能体和工作流配置,实现需求文档自动解析与结构化测试用例生成。该方案显著提升测试效率,特别适合敏捷开发中频繁变更的需求场景,帮助测试工程师快速应对挑战。

weixin_42526015的博客 209

【洛谷】P1908 逆序对(归并排序+快速读入)题解

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

360°顺滑 1587

ENVI SARscape安装全攻略:从下载到汉化一步到位(附最新试用申请链接)

本文提供ENVI SARscape从下载安装到汉化的完整指南,特别针对InSAR(合成孔径雷达干涉测量)分析环境搭建。详细介绍了系统要求、分步安装流程、汉化优化方法及硬件加速配置,并分享数据处理验证和常见问题解决方案,帮助用户高效搭建遥感数据分析平台。

rnn9storyteller的博客 1407

激光光束质量评估与光斑尺寸计算:从理论到MATLAB实践

本文详细解析激光光束质量评估与光斑尺寸计算的理论基础及MATLAB实践方法,重点介绍M²因子的测量与应用。通过高斯光束模型、CCD成像法和MATLAB算法实现,帮助读者掌握从理论到实践的完整流程,提升激光系统调试与评估能力。

weixin_29083373的博客 448

线段树/树状数组 | 洛谷P1908 逆序对题解

本文总结了计算逆序对数量的两种高效方法:归并排序和树状数组/线段树。归并排序在排序过程中通过合并阶段统计逆序对,时间复杂度为O(nlogn)。树状数组和线段树则需先离散化数据,通过动态维护和查询区间统计逆序对。树状数组代码更简洁,但线段树适用性更广。文中提供了相关代码实现,并比较了两种数据结构的差异,强调处理离散化和重复元素的技巧。两种方法都能在合理复杂度内解决大规模逆序对问题。

2501_93040725的博客 514

国产大模型编程能力深度分析报告(2026年5月更新版)

2026年5月国产大模型编程能力报告显示,主流模型迎来重大升级。DeepSeek V4以1.6T参数创性能新高,Qwen3.6-Plus支持原生多模态编程,MiniMax M2.7转向闭源并优化Agent编码,Kimi K2.6成为商业化成熟的主力模型,GLM-5开源并涨价30%。阿里云百炼推出双轨订阅体系,区分团队和个人开发者需求。各模型在参数规模、上下文长度、性能表现和适用场景上各具优势,国产AI编程服务正加速向订阅制转型,成本效益显著提升。

Willin Wang 的全栈升级指南 1647

洛谷 P1908 逆序对- 题解

因此,在循环到第 i 项时,前 i−1 项已经加入到树状数组内了 , 树状数组内比 ai​ 大的都会与ai​构成逆序对,因为它们一定出现的更早,所以产生的逆序对数量为i−query(ai​)这启发我们对数据离散化,先将数据排序,再用 11 ~ n 分别对应 n 个数表示它们的相对大小,对新的序列建树状数组空间就够了(n≤5×105)如果用的不是这个方法的树状数组,那么你 WA 也多半是你忘记处理 Q3 中提到的问题了,如果 RE ,多半是空间开小了。复杂度与普通的归并排序相同,为O(Nlog2​N)

Jaylon Wang的专栏 711

【Ranger】mac下Apache Ranger编译安装

a、编译过程中出现测试用例不通过和文件认证错误错误:带上参数-DskipTests=true -Drat.skip=true 重新编译;b、若编译过程中出现缺少jar包的情况,可能下载不了,需要手动自动添加;c、编译所需的其他工具如maven等安装配置略。采用这个会报错,因此我才用了下面一个命令。初始化设置Ranger Admin:执行。然后进入target目录。

九师兄 2103

Python反爬实战|动态渲染+高可用IP代理集群,稳定爬取京东/淘宝10万+商品数据

做Python电商爬虫的同学,应该都对京东、淘宝的反爬机制深有体会——这两个平台的反爬体系,堪称国内网站的天花板,远比普通资讯、政务网站的反爬严格十倍不止。用requests库请求商品列表,返回的永远是只有骨架的空HTML,商品标题、价格、销量全是前端JS异步加载,抓包分析接口发现参数全是加密的signtoken,解密成本无限高;用selenium开无头浏览器爬取,刚爬3-5页就触发风控,页面直接返回403,IP被封禁,甚至连Cookie都直接失效;

专注于Python爬虫开发,分享爬虫技巧、项目实战与反爬经验,使用Scrapy、BeautifulSoup等工具,解决数据抓取难题。 1585

洛谷P1908 逆序对

因此,在循环到第 i 项时,前 i−1 项已经加入到树状数组内了 , 树状数组内比 ai​ 大的都会与ai​构成逆序对,因为它们一定出现的更早,所以产生的逆序对数量为i−query(ai​)这启发我们对数据离散化,先将数据排序,再用 11 ~ n 分别对应 n 个数表示它们的相对大小,对新的序列建树状数组空间就够了(n≤5×105)如果用的不是这个方法的树状数组,那么你 WA 也多半是你忘记处理 Q3 中提到的问题了,如果 RE ,多半是空间开小了。复杂度与普通的归并排序相同,为O(Nlog2​N)

m0_73704684的博客 264

软件崩溃时Visual Studio中看不到有效的调用堆栈,使用Windbg动态调试去分析定位

当在Visual Studio中遇到软件崩溃且无法查看详细调用堆栈时,可以使用Windbg进行动态调试去分析定位问题。

dvlinker的技术专栏 1万+

从信息学奥赛到算法实战:归并排序巧解逆序对问题

本文详细解析了如何利用归并排序高效解决逆序对问题,从暴力解法的不足到分治思想的优化,再到代码实现的关键细节和实战演练。通过洛谷P1908的实例,展示了算法在竞赛中的实际应用,并分享了调试技巧和算法思维的延伸应用。

weixin_29275257的博客 200

Android P车机添加屏幕多指全局自定义手势操作

参照原生状态栏全局下拉手势拦截,实现屏幕全局多指手势响应操作,并对手势进行转换为KeyEvent,以便项目自定义手势行为或应用拦截手势行为。

shusuanly的博客 1251

jdk-8u144-linux-x64.tar.gz.

该资源为搭建Linux系统Java环境用,资源的后缀为tar.gz格式的压缩包

洛谷1972线段树题解

题目传送门:https://www.luogu.org/problemnew/show/P1972 菜的不行的我不会树状数组,只能拿线段树做,利用了一波1908逆序对的那个想法(不会归并排序也拿线段树做的),也就是在动态改变的时候的线段树。 读题的时候要特别注意,L 和R(1 ≤ L ≤ R ≤ N)!!! 首先我们按照右端点排序(虽然其实左右端点排序应该都可以),那么对于一个比如 6 1...

qq_40892508的博客 549

IMSL CNL 7.0.0 (x86-64)Crack

IMSL CNL 7.0.0 (x86-64)Crack intel的算法库破解文件,这是C++版本的破解文件

P1908 逆序对

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

森宝的博客 848

数学建模模型总结

这是本人在两年内准备参加数学建模竞赛搜集到的模型资料,已经经过了本人的筛选和整理,希望能够对准备参加数学建模竞赛的学弟学妹们提供一些帮助!

锂电池充电器电路设计 里面有电路

锂电池充电器电路设计 里面有电路 3.7V升压到5V电路设计。

猫猫TOM和小老鼠JERRY最近又较量上了,但是毕竟都是成年人,他们已经不喜欢再玩那种你 追我赶的游戏,现在他们喜欢玩统计。最近,TOM老猫查阅到一个人类称之为“逆序对”的东西,这东西是这样定义的:对

80,猫猫TOM和小老鼠JERRY最近又较量上了,但是毕竟都是成年人,他们已经不喜欢再玩那种你 追我赶的游戏,现在他们喜欢玩统计。最近,TOM老猫查阅到一个人类称之为“逆序对”的东西,这东西是这样定义的:对于给定的一段正整数序列,逆序对就是序列中a[i]>a[j]且i<j的有序对。知道这概念后,他们就比赛谁先算出给定的一段正整数序列中逆序对的数目输入第一行,一个数n,表示序列中有n个数 接下来n行,输入n个数,表示给定的序列。输出给定序列中逆序对的数目。 样例输入 6 5 4 2 6 3 1

AFEI666666的博客 1853

逆序对【洛谷P1908】

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

ESTHERWXY的博客 582

逆序对 【luogu P1908】C++题解

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

rc_Wechis的博客 1842

【洛谷】【归并排序】P1908 逆序对

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

weixin_30618985的博客 405

归并排序之逆序对

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

weixin_53993066的博客 324

P1908逆序对(树状数组解法)

逆序对 树状数组 P1908

weixin_68643614的博客 887

逆序对

题目描述 猫猫TOM和小老鼠JERRY最近又较量上了,但是毕竟都是成年人,他们已经不喜欢再玩那种你追我赶的游戏,现在他们喜欢玩统计。最近,TOM老猫查阅到一个人类称之为“逆序对”的东西,这东西是这样定义的:对于给定的一段正整数序列,逆序对就是序列中ai>aj且i 输入输出格式 输入格式: 第一行,一个数n,表示序列中有n个数。 第二行n个数,表示给定的序列。 输出格式: 给定序列中逆

wzw-yali的博客 638
上一篇: Codeforces Round 947 (Div. 1 + Div. 2) D. Paint the Tree 题解 DFS
下一篇: 洛谷 P3870 [TJOI2009] 开关 题解 线段树
bbc_ouo
博客等级 码龄3年 2096粉丝 132原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值