当前位置: 首页 > news >正文

【一百零八】【算法分析与设计】P1908 逆序对,P1637 三元上升子序列,树状数组区间和应用

P1908 逆序对

逆序对

题目描述

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

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

Update:数据已加强。

输入格式

第一行,一个数 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 n2500

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

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

请使用较快的输入输出

应该不会 O ( n 2 ) O(n^2) O(n2) 过 50 万吧 by chen_zhe

求解逆序对的个数,按照每一个下标对应元素,以这个元素为二元组前者所拥有的逆序对的个数.
二元组意思是下标{i,j}组合,并且满足i<j.这样作为一个二元组.arr数组中有1~n下标的元素,遍历所有位置的元素,考虑i位置元素作为二元组中,下标较小的一个,看这样的元素构成的逆序对有多少个.

在这里插入图片描述
分别考虑0下标作为二元组较小下标,这样的所有二元组中的逆序对的个数.再考虑1下标作为二元组较小下标,这样的所有二元组中的逆序对的个数,依次类推,
很容易发现这样的详略可以不重不漏遍历所有的情况.

考虑i位置元素作为二元组较小下标,此时要求逆序对的个数,我们需要直到下标i+1~n区间中所有元素值小于i位置元素值的个数,个数就是逆序对的个数.
在这里插入图片描述
构建元素值映射个数的结构,只需要遍历<=i-1的前缀和即可.
很容易发现元素值映射个数结构,元素值可能是负数,并且不需要12345678连续的不少的元素值映射个数.
如果arr数组分别是145563,我们发现2元素值一直都没出现,所以2映射数量是可以不需要的.
因此需要做离散化操作.

在这里插入图片描述

离散化操作,元素值按照从小到大排序并且去重,元素值映射下标,下标从1开始,依次对应.
只需要利用map结构,将所有的元素值加入map中,然后遍历map依次赋值second为1,2,3,…以此类推.
这样我们只需要构建index映射数量的结构,index一定是正数,并且是连续的.

从后往前遍历i位置元素,查询逆序对个数,arr[i]映射index,1~index-1的前缀和,得到的就是逆序对的个数.
更新index位置的个数.以此类推.

动态维护单点更新和区间和操作,利用树状数组.

#include<bits/stdc++.h>
using namespace std;#define int long long
#define endl '\n'int n; // 定义一个全局变量 n,表示序列中的数目
vector<int> arr; // 定义一个全局向量 arr,用来存储输入的序列
int ret; // 定义一个全局变量 ret,用来存储逆序对的数量
map<int, int> arr_index; // 定义一个全局 map,用来存储序列中每个数字的索引// 树状数组类定义
class Tree {
public:vector<int> tree; // 定义一个向量 tree,用来存储树状数组// 计算 lowbitint lowbit(int i) {return i & -i; // 返回 i 和 -i 的按位与,获取最低位的 1}// 在树状数组中增加值void add(int i, int k) {while (i <= n) { // 从索引 i 开始,向上更新树状数组tree[i] += k; // 增加 ki += lowbit(i); // 移动到下一个需要更新的位置}}// 计算前缀和int sum(int i) {int ret = 0; // 初始化结果为 0while (i > 0) { // 从索引 i 开始,向下计算前缀和ret += tree[i]; // 加上当前索引的值i -= lowbit(i); // 移动到下一个需要计算的位置}return ret; // 返回前缀和}// 计算区间和int range(int l, int r) {return sum(r) - sum(l - 1); // 返回区间 [l, r] 的和}// 默认构造函数Tree() {}// 使用给定数组构造树状数组Tree(vector<int> arr) {tree.assign(arr.size(), 0); // 初始化树状数组for (int i = 1; i <= arr.size(); i++) {add(i, arr[i]); // 将数组中的值添加到树状数组中}}
};Tree t1; // 定义一个全局的树状数组对象// 主解题函数
void solve() {ret = 0; // 初始化逆序对数量为 0t1.tree.assign(n + 5, 0); // 初始化树状数组的大小int index = 1; // 初始化索引为 1for (auto& xx : arr_index) {xx.second = index++; // 给每个数字分配一个唯一的索引}for (int i = n; i >= 1; i--) {int index = arr_index[arr[i]]; // 获取当前数字的索引ret += t1.sum(index - 1); // 计算比当前数字小的数字的数量t1.add(index, 1); // 在树状数组中增加当前数字}cout << ret << endl; // 输出逆序对数量
}signed main() {ios::sync_with_stdio(0), cin.tie(0), cout.tie(0); // 快速输入输出cin >> n; // 读取序列的长度arr.assign(n + 5, 0); // 初始化序列数组for (int i = 1; i <= n; i++) {cin >> arr[i]; // 读取序列中的每个数字arr_index[arr[i]]; // 在 map 中记录每个数字}solve(); // 调用解题函数
}

P1637 三元上升子序列

三元上升子序列

题目描述

Erwin 最近对一种叫 thair 的东西巨感兴趣。。。

在含有 n n n 个整数的序列 a 1 , a 2 , … , a n a_1,a_2,\ldots,a_n a1,a2,,an 中,三个数被称作thair当且仅当 i < j < k i<j<k i<j<k
a i < a j < a k a_i<a_j<a_k ai<aj<ak

求一个序列中 thair 的个数。

输入格式

开始一行一个正整数 n n n,

以后一行 n n n 个整数 a 1 , a 2 , … , a n a_1,a_2,\ldots,a_n a1,a2,,an

输出格式

一行一个整数表示 thair 的个数。

样例 #1

样例输入 #1

4 2 1 3 4

样例输出 #1

2

样例 #2

样例输入 #2

5 1 2 2 3 4

样例输出 #2

7

提示

样例2 解释

7 7 7thair 分别是:

  • 1 2 3
  • 1 2 4
  • 1 2 3
  • 1 2 4
  • 1 3 4
  • 2 3 4
  • 2 3 4
数据规模与约定
  • 对于 30 % 30\% 30% 的数据 保证 n ≤ 100 n\le100 n100
  • 对于 60 % 60\% 60% 的数据 保证 n ≤ 2000 n\le2000 n2000
  • 对于 100 % 100\% 100% 的数据 保证 1 ≤ n ≤ 3 × 1 0 4 1 \leq n\le3\times10^4 1n3×104 1 ≤ a i ≤ 1 0 5 1\le a_i\leq 10^5 1ai105

递增三元组,遍历每一个位置元素i,i作为三元组最右侧的k下标,最大的下标,此时拥有的递增三元组的个数.
等价于求1~i-1位置小于我当前位置元素值的递增二元组的个数.
如果一个数组存储1~i-1映射二元组个数,只需要i求前缀和.

维护二元组数组,遍历每一个位置元素i,作为二元组较大的下标,此时拥有的二元组的个数是1~i-1中有多少个比我小的元素个数.
利用上一道题的思路可以利用数组数组求1~i-1中有多少比我小的元素个数.

#include<bits/stdc++.h>
using namespace std;#define int long long // 定义 int 为 long long 类型,方便处理大数
#define endl '\n' // 定义换行符为 endl,方便输出int n; // 定义全局变量 n,表示序列中的数目
vector<int> arr; // 定义全局向量 arr,用于存储输入的序列
int ret; // 定义全局变量 ret,用于存储三元上升子序列的数量
map<int, int> arr_index; // 定义全局 map,用于存储序列中每个数字的索引// 树状数组类定义
class Tree {
public:vector<int> tree; // 定义一个向量 tree,用于存储树状数组// 计算 lowbitint lowbit(int i) {return i & -i; // 返回 i 和 -i 的按位与,获取最低位的 1}// 在树状数组中增加值void add(int i, int k) {while (i <= n) { // 从索引 i 开始,向上更新树状数组tree[i] += k; // 增加 ki += lowbit(i); // 移动到下一个需要更新的位置}}// 计算前缀和int sum(int i) {int ret = 0; // 初始化结果为 0while (i > 0) { // 从索引 i 开始,向下计算前缀和ret += tree[i]; // 加上当前索引的值i -= lowbit(i); // 移动到下一个需要计算的位置}return ret; // 返回前缀和}// 计算区间和int range(int l, int r) {return sum(r) - sum(l - 1); // 返回区间 [l, r] 的和}// 默认构造函数Tree() {}// 使用给定数组构造树状数组Tree(vector<int> arr) {tree.assign(arr.size(), 0); // 初始化树状数组for (int i = 1; i <= arr.size(); i++) {add(i, arr[i]); // 将数组中的值添加到树状数组中}}
};Tree t1, t2; // 定义两个全局的树状数组对象// 主解题函数
void solve() {t1.tree.assign(n + 5, 0); // 初始化第一个树状数组的大小t2.tree.assign(n + 5, 0); // 初始化第二个树状数组的大小int index = 1; // 初始化索引为 1for (auto& xx : arr_index) {xx.second = index++; // 给每个数字分配一个唯一的索引}ret = 0; // 初始化三元上升子序列的数量为 0for (int i = 1; i <= n; i++) {int index = arr_index[arr[i]]; // 获取当前数字的索引t1.add(index, 1); // 在第一个树状数组中增加当前数字t2.add(index, t1.sum(index - 1)); // 在第二个树状数组中增加当前数字左侧比它小的数字的数量ret += t2.sum(index - 1); // 累加比当前数字小的数字的数量,得到三元上升子序列的数量}cout << ret << endl; // 输出三元上升子序列的数量
}signed main() {ios::sync_with_stdio(0), cin.tie(0), cout.tie(0); // 快速输入输出cin >> n; // 读取序列的长度arr.assign(n + 5, 0); // 初始化序列数组for (int i = 1; i <= n; i++) {cin >> arr[i]; // 读取序列中的每个数字arr_index[arr[i]]; // 在 map 中记录每个数字}solve(); // 调用解题函数
}

结尾

最后,感谢您阅读我的文章,希望这些内容能够对您有所启发和帮助。如果您有任何问题或想要分享您的观点,请随时在评论区留言。

同时,不要忘记订阅我的博客以获取更多有趣的内容。在未来的文章中,我将继续探讨这个话题的不同方面,为您呈现更多深度和见解。

谢谢您的支持,期待与您在下一篇文章中再次相遇!

相关文章:

【一百零八】【算法分析与设计】P1908 逆序对,P1637 三元上升子序列,树状数组区间和应用

P1908 逆序对 逆序对 题目描述 猫猫 TOM 和小老鼠 JERRY 最近又较量上了&#xff0c;但是毕竟都是成年人&#xff0c;他们已经不喜欢再玩那种你追我赶的游戏&#xff0c;现在他们喜欢玩统计。 最近&#xff0c;TOM 老猫查阅到一个人类称之为“逆序对”的东西&#xff0c;这东西…...

【RK3568】制作Android11开机动画

Android 开机 logo 分为两种&#xff1a;静态显示和动态显示。静态显示就是循环显示一张图片&#xff1b;动态显示就是以特定帧率顺序显示多张图片 1.准备 android logo 图片 Android logo最好是png格式的&#xff0c;因为同一张图片的情况下&#xff0c;png 格式的比 jpg和b…...

chrony内网同步服务器时间

当前需要在10.26.24.62和10.26.24.61两个服务器上设置chrony同步时间&#xff0c;其中10.26.24.62为NTP时间服务器&#xff0c;10.26.24.61去10.26.24.62同步时间 检查Chrony配置文件&#xff1a; 确认10.26.24.62&#xff08;NTP服务器&#xff09;的配置文件 /etc/chrony/c…...

SSM物流管理系统的设计与实现-计算机毕业设计源码44323

摘 要 科技进步的飞速发展引起人们日常生活的巨大变化&#xff0c;电子信息技术的飞速发展使得电子信息技术的各个领域的应用水平得到普及和应用。信息时代的到来已成为不可阻挡的时尚潮流&#xff0c;人类发展的历史正进入一个新时代。在现实运用中&#xff0c;应用软件的工作…...

STM32CubeIDE使用过程记录

最近在做一款机器人的开发&#xff0c;使用到了STM32CubeIDE&#xff0c;这里记录一些使用技巧方便后续查阅。 STM32CubeIDE使用过程记录 快捷键开启代码自动补全功能看门狗设置CRC设置IO口取反定时器设置 及 定时器中断外部中断GPIO配置STC15单片机GPIO模式配置片内闪存&#…...

angular2开发知识点

目录 文章目录 一、API 网关地址 配置二、服务注册使用三、模块组件注册使用四、html中style类动态绑定1. 单个类的绑定&#xff1a;[class.special]"isSpecial"2. 多个类的绑定&#xff1a;[ngClass]"{selected:status ,saveable: this.canSave,}"3. 单个…...

【机器学习】机器学习与智能交通在智慧城市中的融合应用与性能优化新探索

文章目录 引言机器学习与智能交通的基本概念机器学习概述监督学习无监督学习强化学习 智能交通概述交通流量预测交通拥堵管理智能信号控制智能停车管理 机器学习与智能交通的融合应用实时交通数据分析数据预处理特征工程 交通流量预测与优化模型训练模型评估 智能信号控制与优化…...

走的人多了,也便成了路(七)

好多年前就听到这样的说法&#xff1a;一流的企业做标准&#xff0c;二流的企业做品牌&#xff0c;三流的企业做产品。 在通信行业待久了&#xff0c;经历了移动通信技术标准的发展历程&#xff0c;体会到很多事情没有那么神秘&#xff0c;甚至由于一些偶然因素的出现&#xff…...

UE5中在地形中加入湖、河

系统水资产添加 前提步骤123 完成 前提 使用版本 UE5.0.3,使用插件为UE内置的Water和water Extras. 步骤 1 记得重启 2 增加地形&#xff0c;把<启用编辑图层>勾选 如果地形没有勾选上编辑图层&#xff0c;那么就会导致湖、河等水景象无法融入地形。 如果忘记勾选…...

【280个shell脚本】----提示运维工作效率

1.MySQL 数据库备份单循环 #!/bin/bash DATE$(date %F_%H-%M-%S) HOSTlocalhost USERbackup PASS123.com BACKUP_DIR/data/db_backup DB_LIST$(mysql -h$HOST -u$USER -p$PASS -s -e "show databases;" 2>/dev/null |egrep -v "Database|information_schema…...

从零开始搭建Electron项目之运行例程

最好的学习方式就是&#xff1a;给一段能够运行的代码示例。 本文给出了例程资源&#xff0c;以及运行的步骤。 在国内开发electron有一点特别不好&#xff0c;就是如果不爬梯子&#xff0c;下载依赖容易出错。 一、例程资源 到如下路径下载例程到本地。 GitCode - 全球开发者…...

MySQL逻辑备份

目录 一.mysqldump 基本命令&#xff1a; 参数选项&#xff1a; 示例 备份整个数据库 备份多个数据库 备份所有数据库 仅备份数据库结构 仅备份特定表 添加选项以有效处理锁表问题 恢复数据 恢复数据库 恢复库中的表 使用source恢复 注意事项 二. mysqlpu…...

python 获取网页链接图片

python 获取 网页图片 在Python中&#xff0c;可以使用requests库获取网页内容&#xff0c;再使用BeautifulSoup解析网页&#xff0c;提取图片链接&#xff0c;最后保存图片到本地。以下是一个简单的例子&#xff1a; import requests from bs4 import BeautifulSoup import o…...

Leetcode 力扣114. 二叉树展开为链表 (抖音号:708231408)

给你二叉树的根结点 root &#xff0c;请你将它展开为一个单链表&#xff1a; 展开后的单链表应该同样使用 TreeNode &#xff0c;其中 right 子指针指向链表中下一个结点&#xff0c;而左子指针始终为 null 。展开后的单链表应该与二叉树 先序遍历 顺序相同。 示例 1&#xf…...

文刻ai工具跟绘唐AI工具有什么区别

文刻AI工具和绘唐AI工具是两种不同的人工智能工具。点击查看 文刻AI工具是一种自然语言处理工具&#xff0c;可以用于生成、修改和校对文本。它可以帮助用户更高效地写作&#xff0c;提供词汇和语法建议&#xff0c;检查拼写和语法错误&#xff0c;并提供自动补全和自动纠正功…...

手写kNN算法的实现-用欧几里德空间来度量距离

kNN的算法思路&#xff1a;找K个离预测点最近的点&#xff0c;然后让它们进行投票决定预测点的类型。 step 1: kNN存储样本点的特征数据和标签数据step 2: 计算预测点到所有样本点的距离&#xff0c;关于这个距离&#xff0c;我们用欧几里德距离来度量&#xff08;其实还有很多…...

IGraph使用实例——线性代数计算(blas)

1 概述 在图论中&#xff0c;BLAS&#xff08;Basic Linear Algebra Subprograms&#xff09;并不直接应用于图论的计算&#xff0c;而是作为一套线性代数计算中通用的基本运算操作函数集合&#xff0c;用于进行向量和矩阵的基本运算。然而&#xff0c;这些基本运算在图论的相…...

【MySQL】(基础篇五) —— 排序检索数据

排序检索数据 本章将讲授如何使用SELECT语句的ORDER BY子句&#xff0c;根据需要排序检索出的数据。 排序数据 还是使用上一节中的例子,查询employees表中的last_name字段 SELECT last_name FROM employees;输出结果&#xff1a; 发现其输出并没有特定的顺序。其实&#xf…...

C++ C_style string overview and basic Input funcitons

write in advance 最近在做题&#xff0c;遇到一个简单的将console的输入输出到文件中的简单题目&#xff0c;没有写出来。悔恨当初没有踏实地总结string 相关的 I/O 以及与文件的操作。这篇文章旨在记录基础的字符I/O, 简单常用的文件I/O操作函数。 当然&#xff0c;你会说C…...

VS2022+Qt雕刻机单片机马达串口上位机控制系统

程序示例精选 VS2022Qt雕刻机单片机马达串口上位机控制系统 如需安装运行环境或远程调试&#xff0c;见文章底部个人QQ名片&#xff0c;由专业技术人员远程协助&#xff01; 前言 这篇博客针对《VS2022Qt雕刻机单片机马达串口上位机控制系统》编写代码&#xff0c;代码整洁&a…...

进程地址空间(比特课总结)

一、进程地址空间 1. 环境变量 1 &#xff09;⽤户级环境变量与系统级环境变量 全局属性&#xff1a;环境变量具有全局属性&#xff0c;会被⼦进程继承。例如当bash启动⼦进程时&#xff0c;环 境变量会⾃动传递给⼦进程。 本地变量限制&#xff1a;本地变量只在当前进程(ba…...

C++ 求圆面积的程序(Program to find area of a circle)

给定半径r&#xff0c;求圆的面积。圆的面积应精确到小数点后5位。 例子&#xff1a; 输入&#xff1a;r 5 输出&#xff1a;78.53982 解释&#xff1a;由于面积 PI * r * r 3.14159265358979323846 * 5 * 5 78.53982&#xff0c;因为我们只保留小数点后 5 位数字。 输…...

《基于Apache Flink的流处理》笔记

思维导图 1-3 章 4-7章 8-11 章 参考资料 源码&#xff1a; https://github.com/streaming-with-flink 博客 https://flink.apache.org/bloghttps://www.ververica.com/blog 聚会及会议 https://flink-forward.orghttps://www.meetup.com/topics/apache-flink https://n…...

ArcGIS Pro制作水平横向图例+多级标注

今天介绍下载ArcGIS Pro中如何设置水平横向图例。 之前我们介绍了ArcGIS的横向图例制作&#xff1a;ArcGIS横向、多列图例、顺序重排、符号居中、批量更改图例符号等等&#xff08;ArcGIS出图图例8大技巧&#xff09;&#xff0c;那这次我们看看ArcGIS Pro如何更加快捷的操作。…...

【生成模型】视频生成论文调研

工作清单 上游应用方向&#xff1a;控制、速度、时长、高动态、多主体驱动 类型工作基础模型WAN / WAN-VACE / HunyuanVideo控制条件轨迹控制ATI~镜头控制ReCamMaster~多主体驱动Phantom~音频驱动Let Them Talk: Audio-Driven Multi-Person Conversational Video Generation速…...

招商蛇口 | 执笔CID,启幕低密生活新境

作为中国城市生长的力量&#xff0c;招商蛇口以“美好生活承载者”为使命&#xff0c;深耕全球111座城市&#xff0c;以央企担当匠造时代理想人居。从深圳湾的开拓基因到西安高新CID的战略落子&#xff0c;招商蛇口始终与城市发展同频共振&#xff0c;以建筑诠释对土地与生活的…...

wpf在image控件上快速显示内存图像

wpf在image控件上快速显示内存图像https://www.cnblogs.com/haodafeng/p/10431387.html 如果你在寻找能够快速在image控件刷新大图像&#xff08;比如分辨率3000*3000的图像&#xff09;的办法&#xff0c;尤其是想把内存中的裸数据&#xff08;只有图像的数据&#xff0c;不包…...

9-Oracle 23 ai Vector Search 特性 知识准备

很多小伙伴是不是参加了 免费认证课程&#xff08;限时至2025/5/15&#xff09; Oracle AI Vector Search 1Z0-184-25考试&#xff0c;都顺利拿到certified了没。 各行各业的AI 大模型的到来&#xff0c;传统的数据库中的SQL还能不能打&#xff0c;结构化和非结构的话数据如何和…...

软件工程 期末复习

瀑布模型&#xff1a;计划 螺旋模型&#xff1a;风险低 原型模型: 用户反馈 喷泉模型:代码复用 高内聚 低耦合&#xff1a;模块内部功能紧密 模块之间依赖程度小 高内聚&#xff1a;指的是一个模块内部的功能应该紧密相关。换句话说&#xff0c;一个模块应当只实现单一的功能…...

《Offer来了:Java面试核心知识点精讲》大纲

文章目录 一、《Offer来了:Java面试核心知识点精讲》的典型大纲框架Java基础并发编程JVM原理数据库与缓存分布式架构系统设计二、《Offer来了:Java面试核心知识点精讲(原理篇)》技术文章大纲核心主题:Java基础原理与面试高频考点Java虚拟机(JVM)原理Java并发编程原理Jav…...