逆序对略解

news/2025/10/30 20:39:24/文章来源:https://www.cnblogs.com/Dlyim/p/19178099

逆序对

定义

在一个数列中,如果前面的数字大于后面的数字,那么这两个数字就构成了一个逆序对

求逆序对

有3种方法:暴力归并排序线段树

1.暴力算法

枚举i和j(i<j),并判断是否满足a[j]<a[i]

for(int i=1;i<n;i++){for(int j=i+1;j<=n;j++){if(a[i]>a[j]) ans++;}}

时间复杂度:O(n²)

2.归并排序

首先知道归并排序的原理:每次把数组平均分成两组,直至每一组只有一个元素,那这一部分一定有序,再用有序部分继续比较排序,进行合并。这样最后合并出来的数组就是有序的

例:

1 3 5 7 9        2 4 6 8 10

① 由于1<2,所以把1放入答案数组

1

② 因为3>2,所以把2放入答案数组

1 2

③ 因为3<4,所以把3放入答案数组

1 2 3

……

最终,答案数组变为

1 2 3 4 5 6 7 8 9 10

我们观察操作①②③,发现它是在比较两个部分的元素大小。

第②步中,发现3>2,由于每个部分都是有序的,因为前面组中3后面的数都比3大,所以前面组中3以及之后的数字都会与2组成逆序对,所以只需要再归并排序的基础上,当前面元素大于后面元素时计算逆序对个数即可

//a是当前数组,t是答案数组
void mergesort(int l,int r){if(l>=r) return;int mid=(l+r)>>1;mergesort(l,mid);mergesort(mid+1,r);int k=0,i=l,j=mid+1;while(i<=mid&&j<=r){if(a[i]<=a[j]) t[++k]=a[i++];else{t[++k]=a[j++];ans+=mid-i+1;}}while(i<=mid) t[++k]=a[i++];while(j<=r) t[++k]=a[j++];for(i=l,k=0;i<=r;i++) a[i]=t[++k];return;
}

时间复杂度:O(n long n)

3.树状数组

树状数组的作用是求前缀和,如何用树状数组表示逆序对数?

其实网上有2种思路,感觉都很神奇。

1.记录下标法

开struct存每一位的值(val)和下标(id),然后按照val降序对数组进行排序。针对每一位,让这一位在树状数组中的位置+1,然后求上一个位置的前缀和,就是当前数值所构成的一部分逆序对数。

原理

因为数组按照权值降序排序,所以处理当前元素时,树状数组中已存在的所有元素值都大于等于当前元素值,满足a[i]>a[j]的条件,接下来需要满足i<j,所以就找j上一位的前缀和,因为每一位只有一个权值,所以树状数组中的值只可能为0和1,即为这一位有数字/没数字,所以前缀和就是1的个数,即为比j小的下标的个数,满足i<j,所以上一位的前缀和就是这一位与前面数的逆序对数

当val值相等的时候,需要按id从大到小排序,这是为了防止将相同的数字错误的当作逆序对数。假设下标2,4存的数值都是10,如果先处理2下标,那么2下标就会被标记,接下来处理4下标的时候,由于2<4,所以计算前缀和会把2下标也计算上,这样是错误的。

(洛谷P1908)

#include <bits/stdc++.h>
typedef long long ll;
using namespace std;
const int N=5e5+10;
ll n,ans;
struct node{ll id,val;
}a[N];
struct tree{ll c[N];void update(ll p,ll x){for(;p<=n;p+=(p&-p)) c[p]+=x;return ;}ll ask(ll p){ll ans=0;for(;p;p-=(p&-p)) ans+=c[p];return ans;}
}t;
bool cmp(node a1,node a2){if(a1.val!=a2.val) return a1.val>a2.val;return a1.id>a2.id;
}
int main(){scanf("%lld",&n);for(int i=1;i<=n;i++){scanf("%lld",&a[i].val);a[i].id=i;}sort(a+1,a+n+1,cmp);for(int i=1;i<=n;i++){t.update(a[i].id,1);ans+=t.ask(a[i].id-1);}printf("%lld",ans);return 0;
}

时间复杂度:O(n long n)

2.记录数值法

记录每个数值出现的次数,到处理当前位时,让当前位的数值在树状数组中的位置+1,然后求这个数值在树状数组中的前缀和,并用i减去它。

原理

由于记录的是每一个数值出现的次数,所以处理当前元素(i)时,求它的前缀和,就是所有小于等于它的数值的个数,此时满足j<i,所以还需要满足a[i]<a[j],由于前缀和计算的是小于等于,当前是第j个数,所以答案应为i-ask(a[i])

当数组数值过大时需要进行离散化

#include <bits/stdc++.h>
typedef long long ll;
using namespace std;
const int N=5e5+10;
ll n,ans,a;
struct tree{ll c[N];void update(ll p,ll x){for(;p<=n;p+=(p&-p)) c[p]+=x;return ;}ll ask(ll p){ll ans=0;for(;p;p-=(p&-p)) ans+=c[p];return ans;}
}t;
int main(){scanf("%lld",&n);for(int i=1;i<=n;i++){scanf("%lld",&a);t.update(a,1);ans+=i-t.ask(a);}printf("%lld",ans);return 0;
}

时间复杂度:O(n long n)

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/951122.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

解码Shell 脚本编程

Shell 脚本基础 编程语言的分类 编程语言主要分为编译型语言和解释型语言,核心区别在于代码执行前是否需要 “编译” 步骤:类型 核心特点 优势 劣势 典型例子编译型语言 用平台相关编译器将源码一次性翻译成机器码(…

第10天(中等题 滑动窗口)

打卡第十天 2道中等题两个函数: 1.ans = move(t) 是将字符串 t 的内容转移给 ans,而不是进行拷贝。 详细2.substr 是 C++ 字符串的标准成员函数,用于从原字符串中提取子串。 详细 函数原型: string substr(size_t po…

树形dp部分题目总结

树形dp树形dp还是太难了 No.1 P2664 树上游戏 题目直接点开即可,这里不再赘述 我们发现其实直接统计每条路径上的颜色个数并不好统计,即使拆开贡献也是如此 举个例子,你要统计一个节点的贡献,那么你的贡献区间是不…

人工智能之编程基础 Python 入门:第三章 基础语法

人工智能之编程基础 Python 入门:第三章 基础语法人工智能之编程基础 Python 入门 第三章 基础语法@目录人工智能之编程基础 Python 入门前言一、基本语法第一个程序编码标识符行与缩进注释运算符一、算术运算符(Ari…

模块-文本

模块-文本模块:__init__文件中经常方常用的模块名用于快速导入 匿名函数递归:函数自己调用自己的写法叫递归异常处理 try: except excption as e:(报错执行) else: (没报错执行) finally:(无论是否报错都执行)

oier的呻吟

题记: 得之我幸,失之我命哎,马上就要考csp-j/s了 总感觉没复习好,啥都不会 好累 赛前遗言 如果这次没上,也不知道以后会有没有机会碰oi 那个oier曾没有远大的志向 突然想到那一句话 得之我幸,失之我命可能明后天…

进销存软件和ERP是包含关系吗?

进销存软件和ERP是包含关系吗?很多企业老板都会问我这个问题。 尤其是第一次接触信息化系统的时候,常常听人说:ERP比进销存高级、ERP包含进销存、我们先上个进销存,后面再上ERP。 听起来都对,但很多人其实并不清楚…

jenkins 权限控制(用户只能看指定的项目)

jenkins 权限控制(用户只能看指定的项目)转自:https://www.cnblogs.com/lfxx/p/17394304.html 1、在插件管理下载Role-based Authorization Strategy插件 2、打开全局安全设置,设置授权策略3、在管理角色里新增一个全…

CF1784C Monsters (hard version)

对于添加操作难做考虑时空倒流改为删数。我们先考虑不带修怎么做,显然考虑维护一个指针排序后从左往右扫。如果当前指针如果还是 \(\leq a_i\),则 \(x\leftarrow x+1\),答案加上 \(a_i-x\)。那么我们发现,答案只跟…

[Programming Tips]Teach Yourself Programming in Ten Years by Peter Norvig

https://www.norvig.com/21-days.html中文翻译版: https://web.archive.org/web/20090216071944/http://www.javaresearch.org/article/12568.htm10年编程无师自通FooSleeper 翻译 更新:2005-01-12 10:18:06 版本…

世界上最牛逼的人—黄景行

黄景行是世界上最牛逼的人

X991CN-个人自制计算器

实物图PCB-3D视图硬件架构图:应用处理器: ESP32-S3 CORE: Xtensa LX7 32bit 240MHZ SRAM:320KB SPI-NORFLASH:16MB PSRAM:8MB SPI-NANDFLASH:256MB TF卡(SPI模式) NORFLASH和NANDFLASH均采用6线QSPI模式,由于ESP32-S…

非计算机专业,保姆级申请软著教程

软著对认证高新企业、申请人才政策、或者大学加学分都很有用。 有很多朋友想自己申请软著,但是又不知道怎么申请。 这里小玖给大家分享一下,保姆级申请软著的流程。 一、前期准备 在申请软著前,需要完成一些前期准…

F5重大安全事件:国家级黑客窃取BIG-IP源代码与技术漏洞

网络安全公司F5确认遭受国家级黑客攻击,攻击者窃取了其旗舰产品BIG-IP的源代码和未公开漏洞信息。该事件对全球企业和关键基础设施构成严重威胁,文章详细分析了攻击过程、潜在影响及防御建议。F5重大安全事件:国家级…

2025年功效型洗发水品牌推荐榜:二硫化硒去屑洗发水/香氛洗发水/控油蓬松洗发水/MASIL玛丝兰以科技适配多元洗护需求​

随着消费者头皮护理认知升级,功效型洗发水市场在 2025 年持续扩容,去屑、控油、修护等细分需求日益突出。但市场增长也伴随产品功效参差不齐、成分温和性差异大等问题,消费者在选购时常面临 “功效与温和难兼顾”“…

10.30(续)

代码大全2的11-13章的读后感: 第 11 章谈变量命名,直指 “模糊命名导致的理解成本”:很多人写代码时觉得x“y”“tmp” 够用,可过了半个月回头调试,却要花十分钟回忆x到底代表用户 ID 还是订单编号;而 “名称反映…

Python字典 _ 创个秒查流行语的词典

Python字典 _ 创个秒查流行语的词典#声明字典slang_dict = {}slang_dict["觉醒年代"] = "A"slang_dict["双剑"] = "何必"slang_dict["加入"] = "“打不过”&q…

2025铝合金/工业/体育/机库/篷房推荐榜:华烨海特斯五星领跑!德国技术 + 多领域适配,3 家企业凭活动 / 仓储 / 特种场景显优势

随着 2025 年临时空间需求向 “安全化、定制化、长效化” 升级,篷房作为工业仓储、体育赛事、商业活动等场景的灵活空间解决方案,其技术标准与服务响应能力成为选型核心。综合安全性能、场景适配度、资质实力及用户反…

B3612 【深进1.例1】求区间和

本体考的是前缀和 前缀和可以简单理解为「数列的前n项的和」,是一种重要的预处理方式点击查看代码 #include <bits/stdc++.h>using namespace std;int main(){int n;cin >> n;vector<int> a(n + 10…