3.12练习题解
1.台阶问题:

这道题目一看其实很容易想到可以用dp的板子去做,并且只需要用一维dp即可,其中dp的下标表示到达当前阶梯总共有多少种方法,由于结果有可能会很大所以一定要记得边记录边模,代码实现如下:
#include<bits/stdc++.h>
using namespace std;
const int mod = 100003;
int n,k;
int dp[100010];
int main(){ios::sync_with_stdio(false);cin.tie(nullptr);cout.tie(nullptr);cin>>n>>k;dp[0]=dp[1]=1;for(int i=2;i<=n;i++){for(int j=1;j<=k;j++){if(i>=j){dp[i]=(dp[i]+dp[i-j]) % mod;} }}cout<<dp[n]%mod;return 0;
}
2.递增三元组:

这一道题目的意思是比较好理解的,我们需要考虑的是,由于给的N的极限值是1e5,所以暴力的方式时间复杂度n的三方肯定会爆,于是我们就要考虑如何对时间复杂度进行优化。
我们可以这样进行考虑,由于数组b是中间数组,我们不妨先对三个数组进行排序,然后我们对b进行枚举,对于每一次枚举,我们在a数组中找到所有小于当前枚举对应的b数组下标元素的个数,然后再找到c数组中所有大于当前b数组下标所对应的元素个数,再把当前符合条件的总个数加到ans上面即可。
再继续思考我们对于每次枚举,然后在a,c数组中查找符合要求的,都可以通过二分进行查找从而降低时间复杂度。所以代码如下:
#include <iostream>
#include <cstdio>
#include <algorithm>
using namespace std;typedef long long LL;
const int N = 1e5+10;
int num[3][N];int main() {int n;scanf("%d", &n);for(int i = 0; i < 3; ++i) for(int j = 1; j <= n; ++j) scanf("%d", &num[i][j]);for(int i = 0; i < 3; ++i)sort(num[i]+1, num[i]+n+1);LL ans = 0;//枚举B,寻找A满足的个数以及C满足的个数相乘for(int i = 1; i <= n; ++i) {int key = num[1][i];//A中二分查找第一个不小于key的数的下标int pos1 = lower_bound(num[0]+1, num[0]+n+1, key)-num[0]-1;//C中二分查找第一个大于key的数的下标int pos2 = upper_bound(num[2]+1, num[2]+n+1, key)-num[2];if(pos1 >= 1 && pos2 <= n) {ans += (LL)pos1*(n-pos2+1);}}cout<<ans<<endl;return 0;
}
这段代码有需要解释的地方:
num[0]+1:这是指向num数组的第一个元素的下一个位置的指针。换句话说,它指向num数组中的第二个元素。num[0]+n+1:这是指向num数组的最后一个元素的下一个位置的指针。换句话说,它指向num数组之后的第一个位置。lower_bound(num[0]+1, num[0]+n+1, key):这是在num数组的第二个元素和最后一个元素之间(不包括最后一个元素)查找第一个不小于key的元素的迭代器。lower_bound(...)-num[0]-1:这将返回的迭代器与num数组的第一个元素的指针相减,然后减去1。这样,我们得到的是找到的元素在num数组中的索引。
所以,pos1存储的是key在num数组中的位置,如果key不在num数组中,则pos1将是key应该插入的位置,以保持num数组的有序性。
简而言之,这段代码在num数组中查找key的位置,并返回其索引。如果key不在数组中,则返回应该插入key的位置。
在C++中,指针的算术运算实际上是对指针所指向的内存地址进行算术运算。当两个指针指向同一个数组或同一个对象的成员时,它们之间的差值表示两个元素之间的偏移量,这个偏移量是以元素为单位,而不是以字节为单位。
对于数组num,num[0]是一个指向数组第一个元素的指针。当我们执行lower_bound函数时,得到的是一个迭代器,它指向数组中第一个不小于key的元素。这个迭代器也是一个指针,指向数组中的某个元素。
当从lower_bound返回的迭代器中减去num[0]时,得到的是两个指针之间的偏移量,这个偏移量表示从数组的第一个元素到找到的元素之间有多少个元素。因为lower_bound返回的迭代器指向的是数组中的元素,而不是元素之间的空隙,所以这个偏移量实际上就是找到的元素在数组中的下标(从0开始计数)。
最后,减去1,是因为我们希望得到的是下标而不是偏移量。在C++中,数组的下标是从0开始的,而指针的偏移量是从1开始的(即,指向第一个元素的指针偏移量为0,指向第二个元素的指针偏移量为1,依此类推)。因此,减去1将偏移量转换为正确的下标。
所以,lower_bound(...)-num[0]-1的结果就是找到的元素在数组中的下标。
第二种方法:双指针优化:
#include <iostream>
#include <cstdio>
#include <algorithm>
using namespace std;typedef long long LL;
const int N = 1e5+10;
int num[3][N];int main() {int n;scanf("%d", &n);for(int i = 0; i < 3; ++i) for(int j = 1; j <= n; ++j) scanf("%d", &num[i][j]);for(int i = 0; i < 3; ++i)sort(num[i]+1, num[i]+n+1);LL ans = 0;//枚举B,寻找A满足的个数以及C满足的个数相乘int a = 1, c = 1;for(int i = 1; i <= n; ++i) {int key = num[1][i];while(a<=n && num[0][a] < key) a++;while(c<=n && num[2][c] <= key) c++;ans += (LL)(a-1)*(n-c+1);}cout<<ans<<endl;return 0;
}
其实也就是将二分中的部分更改了一下。
之前的双指针算法时间复杂度的瓶颈为:排序O(nlog2n)
考虑是否可以不排序在O(n)的时间内解决此问题呢?
既然要排序实现快速的查找A中小于B[i]的数的个数,可以将数组A中所有元素出现的次数存入一个哈希表中,因为数组中元素的范围只有n5, 可以开一个大的数组cnta 作为哈希表。
在枚举B中元素时,我们需要快速查找找小于B[i]的所有元素的总数,只需要在枚举之前先将求出表中各数的前缀和即可。
查找C与查找A同理可得。
代码如下:
//前缀和
#include <iostream>
#include <cstdio>using namespace std;typedef long long LL;
const int N = 1e5+10;
int A[N], B[N], C[N];
int cnta[N], cntc[N], sa[N], sc[N];int main() {int n;scanf("%d", &n);//获取数i在A中有cntc[i]个,并对cnt求前缀和safor(int i = 1; i <= n; ++i) {scanf("%d", &A[i]);cnta[++A[i]]++;}sa[0] = cnta[0];for(int i = 1; i < N; ++i) sa[i] = sa[i-1]+cnta[i];//B只读取即可for(int i = 1; i <= n; ++i) scanf("%d", &B[i]), B[i]++;//获取数i在C中有cntc[i]个,并对cnt求前缀和scfor(int i = 1; i <= n; ++i) {scanf("%d", &C[i]);cntc[++C[i]]++;}sc[0] = cntc[0];for(int i = 1; i < N; ++i) sc[i] = sc[i-1]+cntc[i]; //遍历B求解LL ans = 0;for(int i = 1; i <= n; ++i) {int b = B[i];ans += (LL)sa[b-1] * (sc[N-1] - sc[b]);}cout<<ans<<endl;return 0;
}
感谢您的观看。
相关文章:
3.12练习题解
1.台阶问题: 这道题目一看其实很容易想到可以用dp的板子去做,并且只需要用一维dp即可,其中dp的下标表示到达当前阶梯总共有多少种方法,由于结果有可能会很大所以一定要记得边记录边模,代码实现如下: #incl…...
Java中实现双向链表
一、目标 最近项目中实现双向链表,同时转为满二叉树。 二、代码 用java实现双向链表的代码如下: class TreeNode {int val;TreeNode left;TreeNode right;TreeNode(int x) { val x; } }public class FullBinaryTree {public TreeNode createTree(int[…...
【DevOps实战之k8s】使用Prometheus和Grafana监控K8S集群
【DevOps实战之k8s】使用Prometheus和Grafana监控K8S集群 目录 【DevOps实战之k8s】使用Prometheus和Grafana监控K8S集群系统架构Kubernetes集群指标抓取指标可视化警告PromQL示例按命名空间统计集群中的Pod数按命名空间重启Pod未就绪的PodCPU过度使用Memory过度使用健康的集群…...
【读论文】【精读】3D Gaussian Splatting for Real-Time Radiance Field Rendering
文章目录 1. What:2. Why:3. How:3.1 Real-time rendering3.2 Adaptive Control of Gaussians3.3 Differentiable 3D Gaussian splatting 4. Self-thoughts 1. What: What kind of thing is this article going to do (from the a…...
JVM理解学习
参考视频 JVM架构总览图 程序计数器 程序计数器,物理上用寄存器实现。 作用: 记住下一条JVM指令的执行地址 特点: 1 是线程私有的,随着线程的创建而创建,随着线程的消息而消息 2 是一小块内存 3 唯一不会内存溢出的地方…...
使用 Ruby 或 Python 在文件中查找
对于经常使用爬虫的我来说,在大多数文本编辑器都会有“在文件中查找”功能,主要是方便快捷的查找自己说需要的内容,那我有咩有可能用Ruby 或 Python实现类似的查找功能?这些功能又能怎么实现? 问题背景 许多流行的文本…...
python实现冒泡排序
冒泡排序是一种简单的排序算法,它重复地遍历要排序的数列,一次比较两个元素,如果他们的顺序错误就把他们交换过来。遍历数列的工作是重复地进行直到没有再需要交换,也就是说该数列已经排序完成。 以下是用Python实现冒泡排序的代…...
大数据开发(HBase面试真题-卷二)
大数据开发(HBase面试真题) 1、HBase读写数据流程?2、HBase的读写缓存?3、在删除HBase中的一个数据的时候,它什么时候真正的进行删除呢?4、HBase的一个region由哪些东西组成?5、HBase的rowkey为…...
基于springboot+vue的线上教育系统(源码+论文)
目录 前言 一、功能设计 二、功能实现 三、库表设计 四、论文 前言 现在大家的生活方式正在被计算机的发展慢慢改变着,学习方式也逐渐由书本走向荧幕,我认为这并不是不能避免的,但说实话,现在的生活方式与以往相比有太大的改变,人们的娱乐方式不仅仅…...
01-shell的自学课-基础变量学习
一、echo变量的一个坑 声明【临时变量】,然后打印出来;(拓展:env是linux的全局变量) [rootgong ~]# xinjizhiwashell [rootgong ~]# echo $xinjizhiwa shell [rootgong ~]# echo $xinjizhiwa-haha shell-haha [rootgo…...
鸿蒙Harmony应用开发—ArkTS声明式开发(基础手势:Span)
作为Text组件的子组件,用于显示行内文本的组件。 说明: 该组件从API Version 7开始支持。后续版本如有新增内容,则采用上角标单独标记该内容的起始版本。 该组件从API Version 10开始支持继承父组件Text的属性,即如果子组件未设置…...
前端框架的演进之路:从静态网页到现代交互体验的探索
前端框架的发展史 随着互联网的快速发展,前端技术也在不断进步,前端框架作为前端开发的重要工具,经历了从简单到复杂、从单一到多元的演变过程。本文将回顾前端框架的发展史,探讨其变迁背后的原因和趋势。 一、静态网页时代 在…...
在Linux/Ubuntu/Debian中设置字体
下载字体。 下载你喜欢的字体,双击并安装。 之后更新字体缓存: fc-cache -f -v安装 GNOME 调整。 GNOME Tweaks 是一个工具,允许你自定义 GNOME 桌面环境的各个方面,包括字体。 如果你还没有安装 GNOME Tweaks: …...
Python 常用内置函数,及实例演示
Python的内置函数非常强大,可以帮助你完成各种任务。以下是20个非常有用的Python内置函数及其使用实例: 1. abs() 返回数字的绝对值。 print(abs(-5)) # 输出:52. all() 如果迭代器的所有元素都为真(或迭代器为空)…...
C++标准输入输出和名字空间
C标准输入输出和名字空间 标准输入输出 在C中,标准输入输出(I/O)是通过标准库中的iostream库来实现的,它提供了一套流(stream)抽象来进行数据的输入和输出操作。这套流抽象包括输入流用于读取数据&#x…...
hive逗号分割行列转换
select * from ( select back_receipt_nos,order_no,reject_no from ods_oneplus.ods_us_wms_reject_order_match_all_d where order_no 10150501385980001 ) t1 lateral view explode(split(t1.back_receipt_nos, ,)) t as back_receipt_no where 1 1;...
Jenkins插件Parameterized Scheduler用法
Jenkins定时触发构建的同时设定参数。可以根据不同的定时构建器设置不同参数或环境变量的值。可以设置多个参数。并结合when控制stage流程的执行。结合when和triggeredBy区分定时构建的stage和手动执行的stage。 目录 什么是Parameterized Scheduler?如何配置实现呢…...
西门子S7.NET通信库【读】操作详解
在使用西门子PLC进行工业自动化控制的过程中,经常需要与PLC进行数据交换。S7.NET是一款广泛应用于.NET平台的西门子PLC通信库,它为开发者提供了一系列的API函数,以便在C#、VB.NET等.NET语言中轻松实现与西门子PLC的数据交互。本文将详细介绍如…...
Qt/C++音视频开发69-保存监控pcm音频数据到mp4文件/监控录像/录像存储和回放/264/265/aac/pcm等
一、前言 用ffmpeg做音视频保存到mp4文件,都会遇到一个问题,尤其是在视频监控行业,就是监控摄像头设置的音频是PCM/G711A/G711U,解码后对应的格式是pcm_s16be/pcm_alaw/pcm_mulaw,将这个原始的音频流保存到mp4文件是会…...
闲聊Swift的枚举关联值
闲聊Swift的枚举关联值 枚举,字面上理解,就是把东西一件件列出来。 在许多计算机语言中,枚举都是一种重要的数据结构。使用枚举可以使代码更简洁,语义性更强,更加健壮。 Swift语言也不例外。但和其他语言相比…...
React 第五十五节 Router 中 useAsyncError的使用详解
前言 useAsyncError 是 React Router v6.4 引入的一个钩子,用于处理异步操作(如数据加载)中的错误。下面我将详细解释其用途并提供代码示例。 一、useAsyncError 用途 处理异步错误:捕获在 loader 或 action 中发生的异步错误替…...
Java 语言特性(面试系列2)
一、SQL 基础 1. 复杂查询 (1)连接查询(JOIN) 内连接(INNER JOIN):返回两表匹配的记录。 SELECT e.name, d.dept_name FROM employees e INNER JOIN departments d ON e.dept_id d.dept_id; 左…...
【Oracle APEX开发小技巧12】
有如下需求: 有一个问题反馈页面,要实现在apex页面展示能直观看到反馈时间超过7天未处理的数据,方便管理员及时处理反馈。 我的方法:直接将逻辑写在SQL中,这样可以直接在页面展示 完整代码: SELECTSF.FE…...
【JavaEE】-- HTTP
1. HTTP是什么? HTTP(全称为"超文本传输协议")是一种应用非常广泛的应用层协议,HTTP是基于TCP协议的一种应用层协议。 应用层协议:是计算机网络协议栈中最高层的协议,它定义了运行在不同主机上…...
蓝桥杯 2024 15届国赛 A组 儿童节快乐
P10576 [蓝桥杯 2024 国 A] 儿童节快乐 题目描述 五彩斑斓的气球在蓝天下悠然飘荡,轻快的音乐在耳边持续回荡,小朋友们手牵着手一同畅快欢笑。在这样一片安乐祥和的氛围下,六一来了。 今天是六一儿童节,小蓝老师为了让大家在节…...
Vue2 第一节_Vue2上手_插值表达式{{}}_访问数据和修改数据_Vue开发者工具
文章目录 1.Vue2上手-如何创建一个Vue实例,进行初始化渲染2. 插值表达式{{}}3. 访问数据和修改数据4. vue响应式5. Vue开发者工具--方便调试 1.Vue2上手-如何创建一个Vue实例,进行初始化渲染 准备容器引包创建Vue实例 new Vue()指定配置项 ->渲染数据 准备一个容器,例如: …...
将对透视变换后的图像使用Otsu进行阈值化,来分离黑色和白色像素。这句话中的Otsu是什么意思?
Otsu 是一种自动阈值化方法,用于将图像分割为前景和背景。它通过最小化图像的类内方差或等价地最大化类间方差来选择最佳阈值。这种方法特别适用于图像的二值化处理,能够自动确定一个阈值,将图像中的像素分为黑色和白色两类。 Otsu 方法的原…...
江苏艾立泰跨国资源接力:废料变黄金的绿色供应链革命
在华东塑料包装行业面临限塑令深度调整的背景下,江苏艾立泰以一场跨国资源接力的创新实践,重新定义了绿色供应链的边界。 跨国回收网络:废料变黄金的全球棋局 艾立泰在欧洲、东南亚建立再生塑料回收点,将海外废弃包装箱通过标准…...
mysql已经安装,但是通过rpm -q 没有找mysql相关的已安装包
文章目录 现象:mysql已经安装,但是通过rpm -q 没有找mysql相关的已安装包遇到 rpm 命令找不到已经安装的 MySQL 包时,可能是因为以下几个原因:1.MySQL 不是通过 RPM 包安装的2.RPM 数据库损坏3.使用了不同的包名或路径4.使用其他包…...
Redis的发布订阅模式与专业的 MQ(如 Kafka, RabbitMQ)相比,优缺点是什么?适用于哪些场景?
Redis 的发布订阅(Pub/Sub)模式与专业的 MQ(Message Queue)如 Kafka、RabbitMQ 进行比较,核心的权衡点在于:简单与速度 vs. 可靠与功能。 下面我们详细展开对比。 Redis Pub/Sub 的核心特点 它是一个发后…...
