1236. 递增三元组:做题笔记

news2024/10/5 14:03:03

目录

暴力

代码

二分

代码

前缀和 

代码

推荐视频讲解


暴力

这道题说的是有三个元素数量相同的数组,想知道有多少个三元组满足:三个数分别来自 A B C数组且呈现递增。

我想的是既然要求递增,那就先把数组数据都排一下序,直接sort函数用起来。因为排了序的话就说明在某个数之后的所有数都是满足条件的,直接进行累加就可以。

第一个数A数组肯定要先遍历一下的(是的我当时做的时候压根没想到其他的),我就想着我们既然想利用排完序的好处,那就从这想。

在第一层循环的基础上,在对第二层数据挑选的时候,就可以利用二分找到我们上面所说的“某个数”,这里的某个数其实也就是当前B数组里第一个大于当前外层循环正在处理的A数组的这个元素,我们知道在这个数之后的B数组中的数都是一种选择的可能。同理,到了最内层对从C数组中选的第三个数的可能性也就是在前两个数确定的这种情况下满足条件的可能性。

这样就枚举了所有可能性,肯定超时的。且这样的写法一个数据都过不了呜呜😭

我就没想到到底怎么优化掉第二层循环,,

代码

#include<iostream>
#include<algorithm>
using namespace std;
#define int long long
const int N=1e5+10;
int a[N],b[N],c[N],b1[N],c1[N];
int n;
int find(int q[],int x)
{
	int l=0,r=n;
	while(l<r)
	{
		int mid=(l+r)/2;
		if(q[mid]>x)r=mid-1;
		else l=mid;
	}
	if(q[l]>x)return l;
	else if(q[l]==x)return l+1;
	else return -1;
}
signed main()
{
	ios::sync_with_stdio(0);
	cin.tie(0);
	cout.tie(0);
	
	cin>>n;
	for(int i=0;i<n;i++)cin>>a[i];
	for(int i=0;i<n;i++)cin>>b[i];
	for(int i=0;i<n;i++)cin>>c[i];
	
	sort(a, a+n);
	sort(b, b+n);
	sort(c, c+n);
	
	int cnt=0;
	for(int i=0;i<n;i++)
	{
		
		for(int j=find(b,a[i]);j<n;j++)
		{
			//第三层循环还是好优化的(不过没什么卵用,因为双层循环仍然tle😜)
			/*
			for(int k=find(c,b[j]);k<n && k!=-1;k++)
			{
				cnt++;
			}*/

			int k=find(c,b[j]);
			cnt+=n-k;
		}
	}
	cout<<cnt;
	return 0;
 } 

二分

就是看了讲解才知道我们想降成一层循环,那留下来的这层循环就必须是中间的B数组。

因为A B C 三元组想递增嘛,那 A<B,C>B。遍历B数组每个元素,可以通过二分找到A数组中第一个大于当前B数组中元素的数的位置,和C数组中第一个大于当前B数组中元素的数的位置,通过元素总数与该位置的相减,得到其中间的元素个数。

我们可以写二分模板,也可以使用 lower_bound和upper_bound 函数,感觉直接用函数很方便。就像那个sort函数一样。

由于这两个函数的操作对象应该是有序的,我们需要对数组进行排序。

补充一下这两个函数的用法:

lower_bound(begin, end, value):在从小到大排好序的数组中,在数组的 [begin, end) 区间中二分查找第一个大于或等于value的数,找到返回该数字的地址,不存在则返回end。通过返回的地址减去起始地址begin,得到找到数字在数组中的下标


upper_bound(begin, end, value):在从小到大排好序的数组中,在数组的 [begin, end) 区间中二分查找第一个大于value的数,找到返回该数字的地址,不存在则返回end。通过返回的地址减去起始地址begin,得到找到数字在数组中的下标。


这两个函数的时间复杂度都是O(logN),其中N是搜索空间中的元素数量。 

代码

#include<iostream>
#include<algorithm>
using namespace std;
#define int long long
const int N=1e5+10;
int a[N],b[N],c[N];
int n;
signed main()
{
	ios::sync_with_stdio(0);
	cin.tie(0);
	cout.tie(0);
	
	cin>>n;
	for(int i=0;i<n;i++)cin>>a[i];
	for(int i=0;i<n;i++)cin>>b[i];
	for(int i=0;i<n;i++)cin>>c[i];
	
	sort(a, a+n);
	sort(b, b+n);
	sort(c, c+n);
	
	int cnt=0;
	for(int i=0;i<n;i++)
	{
		int l=lower_bound(a,a+n,b[i])-a,r=n-(upper_bound(c,c+n,b[i])-c);
		cnt+=l*r;
	}
	cout<<cnt;
	return 0;
 }

l 是数组 a 中小于 b[i] 的元素的数量,r 是数组 c 中大于 b[i] 的元素的数量。

前缀和 

这里前缀和的思路也是以B数组的遍历为主。

记录下所有数字出现的次数,预处理出前缀和,对A C数组进行排序,与B数组当前处理的元素进行比较,通过前缀和的运算得到A数组小于当前元素的个数,和C数组大于当前元素的个数,将这两个数相乘,并随着B数组的遍历对每一种情况进行累加得到最终结果。

关于前缀和的运算:A数组想得到小于当前元素的个数,直接b[i]-1的前缀和得到的就是想要的区间的前缀和  ( sa[b[i]-1] )

C数组想得到大于当前元素的个数,用 N 处的前缀和减去b[i]当前元素的前缀和即可( sc[N]-sc[b[i]] )

需要注意的是,由于数组中每个元素的数据范围是0-1e5,因此在前缀和计算中要从0开始,循环1e5次,关于数组越界问题:

代码

#include<iostream>
#include<algorithm>
using namespace std;
#define int long long
const int N=1e5+10;
int a[N],b[N],c[N];
int a1[N],c1[N];//存放每个数出现次数
int sa[N],sc[N];//计算a1,c1的前缀和
int as[N],cs[N];//通过前缀和的运算处理出所有可能的情况
//as代表比b[i]小的数的个数  cs代表比b[i]大的数的个数
int n;
signed main()
{
	ios::sync_with_stdio(0);
	cin.tie(0);
	cout.tie(0);
	
	cin>>n;
	for(int i=0;i<n;i++)cin>>a[i];
	for(int i=0;i<n;i++)cin>>b[i];
	for(int i=0;i<n;i++)cin>>c[i];
	
	for(int i=0;i<n;i++)a1[a[i]]++;
	for(int i=0;i<=N;i++)sa[i]=sa[i-1]+a1[i];
	for(int i=0;i<n;i++)as[i]=sa[b[i]-1];
	
	for(int i=0;i<n;i++)c1[c[i]]++;
	for(int i=0;i<=N;i++)sc[i]=sc[i-1]+c1[i];
	for(int i=0;i<n;i++)cs[i]=sc[N]-sc[b[i]];
	
	int cnt=0;
	for(int i=0;i<n;i++)
	{
		cnt+=as[i]*cs[i];
	}
	cout<<cnt;
	return 0;
 }

推荐视频讲解

【蓝桥杯真题,递增三元组,前缀和问题】

老师讲的很清晰。推荐观看

AcWing 1236. 递增三元组(三种算法+胎教注释)​​​​​​​

这个题解不知道大家能看到不能。


感觉思路理解还行,但是就是明白了思路到写对题之间还有很长距离,好多细节问题emm. 

哎好难🥀🥀🥀🥀

有问题欢迎指出,一起加油!!!!

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

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

相关文章

鸿蒙:滑动条组件Slider

滑动条组件&#xff0c;通常用于快速调节设置值&#xff0c;如音量调节、亮度调节等应用场景。 说明 该组件从API Version 7开始支持。 子组件 无 接口 Slider(options?: {value?: number, min?: number, max?: number, step?: number, style?: SliderStyle, direc…

如何使用potplayer在公网环境访问内网群晖NAS中储存在webdav中的影视资源

&#x1f308;个人主页: Aileen_0v0 &#x1f525;热门专栏: 华为鸿蒙系统学习|计算机网络|数据结构与算法 ​&#x1f4ab;个人格言:“没有罗马,那就自己创造罗马~” #mermaid-svg-D7WJh3JaNVrLcj2b {font-family:"trebuchet ms",verdana,arial,sans-serif;font-siz…

渐变颜色作图

clear clc close all % 生成 x 值 x linspace(0, 5, 1000); % 计算对应的 y 值&#xff08;二次函数分布&#xff09; y x .^ 2; % 添加一些随机噪声 y y randn(size(y)); clinspace(1,10,length(x)); arry1[x,y]; arry2sortrows(arry1,2,descend); arry3[arry2,c]…

LabVIEW双通道太阳射电频谱观测系统

LabVIEW双通道太阳射电频谱观测系统 开发了一个基于LabVIEW平台开发的双通道高速太阳射电频谱观测系统。该系统实时监测太阳射电爆发&#xff0c;具有随机性、持续时间短、变化快等特点。通过高速信号采集卡实现1.5 GS/s的信号采集&#xff0c;时间分辨率可达4ms&#xff0c;频…

跑腿小程序|基于微信小程序的跑腿平台小程序设计与实现(源码+数据库+文档)

跑腿平台小程序目录 目录 基于微信小程序的跑腿平台小程序设计与实现 一、前言 二、系统设计 三、系统功能设计 1、用户信息管理 2、跑腿任务管理 3、任务类型管理 4、公告信息管理 四、数据库设计 五、核心代码 六、论文参考 七、最新计算机毕设选题推荐 八、…

MySQL 优化及故障排查

目录 一、mysql 前置知识点 二、MySQL 单实例常见故障 故障一 故障二 故障三 故障四 故障五 故障六 故障七 故障八 三、MySQL 主从故障排查 故障一 故障二 故障三 四、MySQL 优化 1.硬件方面 &#xff08;1&#xff09;关于 CPU &#xff08;2&#xff09;关…

备战蓝桥杯---贪心刷题2

话不多说&#xff0c;直接看题&#xff1a; 首先我们大致分析一下&#xff0c;先排序一下&#xff0c;Kn&#xff0c;那就全部选。 当k<n时&#xff0c;k是偶数&#xff0c;那么结果一定非负&#xff0c;因为假如负数的个数有偶数个&#xff0c;那么我们成对选它&#xff0…

单链表的一些个人易错的问题(有理解不正确的地方请大佬指正)

请看下列代码 代码1&#xff1a;&#xff08;正确示范&#xff09; #include<stdio.h> #include<stdlib.h> struct node {int data;struct node *next;}; int main() {int n;int a;printf("请输入数字个数&#xff1a;");scanf("%d",&n)…

行车记录打不开?数据恢复有高招!

行车记录打不开&#xff0c;是许多车主在使用行车记录仪时常遇到的问题。当启动设备时&#xff0c;屏幕无反应或提示错误&#xff0c;让人不禁焦虑&#xff0c;担心重要的行车记录丢失。 行车记录打不开原因分析 行车记录打不开&#xff0c;其背后的原因可能复杂多样。硬件故障…

每日学习笔记:C++ STL算法分类

非更易型 更易型 移除型 变序型 排序型 已排序区间算法 数值型算法

【嵌入式系统设计师】软考2024年5月报名流程及注意事项

2024年5月软考嵌入式系统设计师报名入口&#xff1a; 中国计算机技术职业资格网&#xff08;http://www.ruankao.org.cn/&#xff09; 2024年软考报名时间暂未公布&#xff0c;考试时间上半年为5月25日到28日&#xff0c;下半年考试时间为11月9日到12日。不想错过考试最新消息…

行车记录打不开?别慌,数据恢复有高招!

行车记录打不开&#xff0c;这恐怕是许多车主都曾经遭遇过的烦恼。在驾驶途中&#xff0c;行车记录仪本应是记录美好瞬间、保障行车安全的重要工具&#xff0c;但一旦它出现打不开的情况&#xff0c;所有的期待与信赖便瞬间化为乌有。面对这种情况&#xff0c;我们该如何应对&a…

【C++的奇迹之旅(二)】C++关键字命名空间使用的三种方式C++输入输出命名空间std的使用惯例

文章目录 &#x1f4dd;前言&#x1f320; C关键字(C98)&#x1f309; 命名空间&#x1f320;命名空间定义&#x1f309;命名空间使用 &#x1f320;命名空间的使用有三种方式&#xff1a;&#x1f309;加命名空间名称及作用域限定符&#x1f320;使用using将命名空间中某个成员…

SAP ABAP批量复制PFCG角色并生效

文章目录 需求整体流程1. 检查角色是否存在2. 复制角色3. 批量生成参数文件4. 如果角色用户还是出现未比较&#xff0c;可在PFCG界面选择批量比较 细节上载模板代码&#xff1a; 小结 需求 最近碰到一个需求&#xff0c;需要对大批量的PFCG角色进行复制并使其生效 整体流程 …

Java 堆外内存及调优

文章目录 直接内存简介为什么DirectByteBuffer可以优化 IO 性能 直接内存的分配直接内存的回收直接内存跟踪与诊断 直接内存简介 直接内存(Direct Memory) 并不是虚拟机运行时数据区的一部分&#xff0c;并非Java虚拟机规范中定义的内存区域。但是这部分内存的频繁使用&#x…

动手机器学习支持向量机+习题

非参数化模型&#xff0c;当数据集规模增大时&#xff0c;其参数量也相应变多 希望从这无数个可以分隔两个点集的超平面中&#xff0c;挑选出与任意一点间隔&#xff08;margin&#xff09;的最小值最大的平面 支持向量机的数学描述 对上式来说&#xff0c;当w和b的大小同时变…

书生·浦语大模型实战营(第二期)-书生·浦语大模型全链路开源体系

课程来源&#xff1a;书生浦语大模型全链路开源体系 1.大模型成为发展通用人工智能的重要途径 专用模型:针对特定任务,一个模型解决一个问题 通用大模型:一个模型应对多种任务、多种模态 2.书生浦语大模型开源历程 书生浦语2.0面向不同的使用需求,每个规格包含三个模型版本:I…

golang语言系列:Authentication、OAuth、JWT 认证策略

云原生学习路线导航页&#xff08;持续更新中&#xff09; 本文是 golang语言系列 文章&#xff0c;主要对编程通用技能 Authentication、OAuth、JWT 认证策略 进行学习 1.Basic Authentication认证 每个请求都需要将 用户名密码 进行base64编码后&#xff0c;放在请求头的Aut…

04-MySQL数据库-权限管理

一、查看权限 1&#xff0c;查看系统所有权限 mysql> show privileges; 权限字段介绍 privileges #权限名称 context #对象&#xff0c;表示可以对数据库&#xff0c;那些资源、进行哪些操作&#xff1b; comment #描述&#xff0c;备注解释说明&#xff1b; Grant…

C++刷题篇——04找等值元素

一、题目 二、解题思路 1、分割后放进二维数组 2、使用map&#xff0c;key为数值&#xff0c;value为其坐标 3、遍历二维数组元素&#xff0c;再在map中找该元素对应的value值&#xff08;二维数组形式&#xff09;&#xff0c;倘若value.size为1&#xff0c;那直接返回-1&…