洛谷 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

PyCharm配置及使用Git教程

平时习惯在Windows下开发,但是我们又需要实时将远方仓库的代码clone到本地,也需要将自己修改的代码push到远端服务器。

酒酿小圆子呀~ 4万+

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

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

360°顺滑 1587

StarRocks FE启动异常

服务器断电,StarRocks FE 启动失败。

qq_15138049的博客 1112

告别DLTS的模糊地带:手把手教你用拉普拉斯深能级瞬态光谱(LDLTS)精准揪出半导体缺陷

本文详细介绍了拉普拉斯深能级瞬态光谱(LDLTS)技术在半导体缺陷检测中的高分辨率解决方案。相比传统DLTS,LDLTS通过拉普拉斯变换和正则化算法,将分辨率提升至1meV,有效解析复杂重叠缺陷谱,适用于硅、GaN等材料的精确缺陷分析。文章涵盖LDLTS原理、系统搭建、测量流程及工业应用案例,为半导体工艺优化提供强大工具。

weixin_29238147的博客 193

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

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

2501_93040725的博客 514

深入解析西门子S7通信协议:从抓包到实战应用

本文深入解析西门子S7通信协议,从环境搭建、抓包分析到实战应用,提供了一套完整的协议分析方法。通过Wireshark工具进行抓包分析,详细拆解了S7协议各层结构,并结合真实案例,展示了如何利用抓包技术解决通信故障、优化性能及进行安全审计,是掌握工业通信底层原理的实用指南。

weixin_29224529的博客 281

洛谷 P1908 逆序对- 题解

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

Jaylon Wang的专栏 711

结构优化软件:OptiStruct_(11).拓扑优化

在OptiStruct中,设计空间可以通过定义设计区域来实现。设计区域是结构中可以进行材料变化的部分。几何区域:通过几何选择工具选择特定的区域。网格区域:通过网格选择工具选择特定的单元。假设我们有一个简单的梁结构模型,网格文件为beam.fem。我们希望在梁的中部进行拓扑优化,以减轻重量并保持刚度。

kkchenjj的博客 1367

18、项目运行与调试全攻略

本文详细介绍了在IntelliJ IDEA中进行项目运行与调试的完整流程,涵盖运行配置的创建与管理、临时配置的使用与保存、运行窗口的控制台操作及多程序并行运行的处理。同时,讲解了如何通过调试器定位和修复语法错误、运行时错误及逻辑错误,并结合ACME项目演示了第三方库Log4J的集成方法和命令行客户端的功能改进。文章还提供了调试流程图,帮助开发者系统掌握IDEA的强大调试功能,提升开发效率与代码质量。

svm4gardener的博客 75

洛谷P1908 逆序对

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

m0_73704684的博客 264

论文阅读 AIED 2024 Coding with AI: How Are Tools Like ChatGPT Being Used by Students in Foundational Pro

该论文题为《Coding with AI: How Are Tools Like ChatGPT Being Used by Students in Foundational Programming Courses》,由美国犹他州立大学的 Aashish Ghimire 与 John Edwards 共同撰写,发表于人工智能与教育领域顶级会议。

CSPhD-winston的博客 307

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

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

weixin_29275257的博客 200

基于Python的智能动漫更新监控爬虫系统:从原理到实战

本文详细介绍了如何使用Python构建一个智能化的动漫更新监控系统,涵盖从基础爬虫到高级自动化监控的全套解决方案。文章将深入探讨最新的网络爬虫技术,包括异步请求、反反爬策略、智能解析算法等,并提供完整的代码实现和性能优化方案。通过本系统,用户可以实时获取多个动漫平台的更新信息,并通过多种渠道接收通知。关键词:Python爬虫、动漫监控、自动化通知、异步爬虫、反反爬策略。

2201_76125261的博客 902

Outlook Express 6 (OE6) for Win7/Win8/Win10

英文版 Outlook Express6.0, 兼容Win7/Win10/WinXP,解压就可用。

洛谷1972线段树题解

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

qq_40892508的博客 549

RU DOS版、EFI版32bit/64bit BIOS常用工具

DOS版、EFI版的RU工具,可用来查看IO、MEM、PCI、SMBIOS等资源。亲测在EFI SHELL下可用。

P1908 逆序对

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

森宝的博客 848

怀旧版电脑GBC模拟器

再现原版GBC掌机的界面,电脑运行连游戏界面都一样大小,很怀旧,很真实,(英文版)强烈推荐,很小的文件,很难才找到的。

猫猫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、付费专栏及课程。

余额充值