算法里面的离散化
一、离散化(discretization)在算法和数据结构中指的是将连续的输入数据映射到离散的值或者范围,从而使得处理和计算变得更高效。通常用于处理大范围或者无限可能的输入,以便将其转化为有限的、可以有效处理的范围。
离散化的定义
离散化的主要目的是将连续的值或大范围的值映射到一个有限的集合中,以便进行高效的存储和处理。这通常通过对连续的数据进行排序、分组、或者映射来实现。
离散化的步骤
- 排序和编号:对所有唯一的连续值进行排序,然后为这些值分配一个唯一的编号。
- 映射:使用一个映射函数,将原始数据的每个值转换为新的编号或索引。
应用场景
-
区间压缩:在处理大范围的整数值时,通过离散化可以将这些值映射到一个较小的范围。例如,处理1到10000的值时,可以将它们映射到1到100的范围内。
-
数据结构优化:在某些数据结构中(如树状数组或线段树),需要将离散化后的值作为索引来优化查询和更新操作。
离散化在以下方面有应用:
- 机器学习:将连续特征转换为离散类别,简化模型处理,例如将年龄分段成“青年”、“中年”、“老年”。
- 图像处理:将图像数据的连续像素值转换为离散的色彩级别,提高处理效率。
- 数据压缩:将连续信号如音频或视频离散化,以减少存储需求。
- 数据库设计:将连续数据映射到离散值,用于更高效的数据索引和查询。
这些应用帮助简化计算、提高效率或改善模型性能。
例子
例子 1:区间压缩
假设有一组连续的坐标值:[100, 150, 300, 600, 900]
。我们希望将这些值映射到更小的范围。
-
排序和编号:
- 排序后的值:
[100, 150, 300, 600, 900]
- 对这些值进行编号:
100 -> 1
,150 -> 2
,300 -> 3
,600 -> 4
,900 -> 5
- 排序后的值:
-
映射:
- 原始值
100
映射到编号1
- 原始值
150
映射到编号2
- 原始值
300
映射到编号3
- 原始值
600
映射到编号4
- 原始值
900
映射到编号5
这样,我们就将原始的连续值压缩到了
[1, 2, 3, 4, 5]
,这使得后续的数据结构(如线段树或树状数组)的操作更为高效。 - 原始值
例子 2:二维离散化
假设有一组二维坐标值:[(10, 20), (15, 30), (30, 60)]
。我们需要将这些坐标值离散化。
-
提取和排序:
- X轴坐标:
[10, 15, 30]
- Y轴坐标:
[20, 30, 60]
- 对X轴坐标编号:
10 -> 1
,15 -> 2
,30 -> 3
- 对Y轴坐标编号:
20 -> 1
,30 -> 2
,60 -> 3
- X轴坐标:
-
映射:
(10, 20)
映射到(1, 1)
(15, 30)
映射到(2, 2)
(30, 60)
映射到(3, 3)
这样,我们将原始的连续坐标转换成离散的坐标,对数据结构的处理(如二维树状数组)将更加高效。
总结
离散化的关键是将原始的、可能是连续或无限范围的数据,转化为有限且可处理的编号或索引。这样不仅优化了存储空间,也提高了数据处理的效率。
二、在算法中,“映射”是指将一个集合中的每个元素通过某种规则或函数转换为另一个集合中的元素的过程。这一概念广泛应用于数据处理、函数设计和数据结构中。以下是映射的详细解释:
1. 基本定义
映射可以被视为一个函数 ( f: A \rightarrow B ),其中 ( A ) 是定义域,( B ) 是值域。对于定义域中的每个元素 ( a \in A ),映射函数 ( f ) 将其转换为值域中的元素 ( b \in B )。形式上,这可以表示为 ( f(a) = b )。
2. 示例
-
数学中的映射:一个简单的数学映射是 ( f(x) = x^2 ),它将每个实数 ( x ) 映射到它的平方 ( x^2 )。
-
数据结构中的映射:在哈希表中,映射是通过哈希函数将键(key)映射到对应的值(value)。例如,键 "name" 可能映射到值 "Alice"。
3. 应用
-
数据转换:在数据处理过程中,可以将数据从一种格式转换为另一种格式。比如,映射函数可以将用户输入的字符串转换为对应的内部数据结构。
-
离散化:在离散化过程中,映射用于将连续的数据转换为离散的值。例如,将地理坐标映射到一个有限的网格系统中。
4. 复杂映射
映射不仅限于一对一关系,还可以是多对一(多个输入映射到一个输出)或一对多(一个输入映射到多个输出)。例如,在关系数据库中,某一用户ID可能映射到多个订单记录。
5. 映射的属性
- 单射(Injective):每个定义域的元素映射到值域中唯一的元素,不存在不同的输入映射到相同的输出。
- 满射(Surjective):定义域中的每个元素都映射到值域中的某个元素,使得值域中的每个元素至少被映射一次。
- 双射(Bijective):既是单射又是满射,即每个定义域的元素都有唯一的值域元素,且值域中的每个元素都有唯一的定义域元素。
映射在算法中扮演着重要角色,它使得数据转化、存储和处理变得更加系统化和高效。
了解了什么是离散化和映射,接下来直接开始做题,用题目实践才是最好的。
题目:区间和
假定有一个无限长的数轴,数轴上每个坐标上的数都是 0。
现在,我们首先进行 n次操作,每次操作将某一位置 x上的数加 c。
接下来,进行 m次询问,每个询问包含两个整数 l 和 r,你需要求出在区间 [l,r] 之间的所有数的和。
输入格式
第一行包含两个整数 n和 m。
接下来 n 行,每行包含两个整数 x 和 c。
再接下来 m 行,每行包含两个整数 l 和 r。
输出格式
共 m 行,每行输出一个询问中所求的区间内数字和。
数据范围
≤x≤
,
1≤n,m≤,
≤l≤r≤
,
−10000≤c≤10000
输入样例:
3 3
1 2
3 6
7 5
1 3
4 6
7 8
输出样例:
8
0
5
离散化的特点:
值域大,个数少。
可以把这n个数映射到它的下标。
常见的问题:
1. 数组a中有重复元素(去重)
2. 如何算出映射后的值?(二分)
此题把下标映射后前缀和求解即可。
#include<iostream>
#include<vector>
#include<algorithm>using namespace std;
typedef pair<int,int> PII;/*定义pair<int,int>类型为PII,就相当于取了一个别名,就是方便使用的时候不输入那么复杂又长的东西。*/
const int N=3e5+10;
/*因为有三个坐标,所以是用的3e5+10的范围。
输入的n个x,m个l,r,就是n+2m个坐标,因为n和m都是10的五次方,所以就是3乘10的5次方,多10是故意开的,害怕越界嘛。*/
int a[N],s[N];
/*这个就是求的区间和,只不过前面还有些步骤,所以这个a[N]数组是存储的值,不是坐标哈;s[N]
还是和前缀和一样,是放的前缀和的值。*/
vector<PII> add,query;
/*观察题目得到,输入的位置x和插入的值c,与后面输入的区间两个边界l,r一样,都是一次输入一对
的数进去,所以这里定义了一个PII类型的vector,来存储要操作的东西。这里面add是存储插入的位置x和值c,而query是查询区间,并求出指定区间的和,所以query存储的是边界l,r的位置*/
vector<int> alls;
/*alls是存储所有的位置的,不管是刚开始的x,还是l,r都存在里面,后面会操作的,很有用处。记住,vector是c++里面的可变数组,所以在进行和数组类似的操作时,也可以像数组那样使用,切记。*/int find(int x){int l=0,r=alls.size()-1;while(l<r){int mid=l+r>>1;//这里是整数,没有小数,所以可以用位运算。if(alls[mid]>=x) r=mid;//二分的第一个模板,相当于求最小值的那个,不用加1。else l=mid+1;}return r+1;//这里你写l+1也可以,反正最后二分l是约等于r的,都可以。/**注意返回的是r+1,就是最低是返回1,因为我要求前缀和,所以就这样。/
}
/*这个函数是利用的二分查找,来查找x在alls可变数组里面的位置,也就是x在alls可变数组的数组下标是多少。这其实就是离散化了,alls数组在之前的操作后,已经变得井然有序,每一个输入的坐标值x,l,r在alls里面都有对应的位置,这就已经将原来范围大,数目少且离散,不好处理的坐标给放在了alls数组里面,所以要注意,这个alls数组里面存的是坐标,如果要求对应的值的话,那么就是,例如:要想查询x位置上的值的话,那么就是:1、先找到x这个坐标在alls数组里面的哪个位置,对应的是alls数组的哪个下标。 2、找到了以后,就能迅速的在alls数组里面找到x坐标所在的位置。 3、找到位置后就直接能找到x所对应的值了。 这就是离散化:1、vector存输入的位置坐标;2、在这个vector里面找到需要的位置坐标。
3、找到以后就可以像之前那样正常操作了,想查值就查值,想求前缀和就求前缀和。*/int main(){int n,m;cin>>n>>m;for(int i=0;i<n;i++){int x,c; cin>>x>>c;add.push_back({x,c});alls.push_back(x);}
/*输入n,m,并且输入x,c,这x,c是插入所需要的值,所以将这两个值存到add这个vector里面。然后顺便把位置x存入alls这个可变数组里面。*/for(int i=0;i<m;i++){int l,r;cin>>l>>r;query.push_back({l,r});alls.push_back(l);alls.push_back(r);}
/*输入l,r,并将后面查询求前缀和所需要的值l,r给存入到query这个vector里面去,同时,l,r这两个表示位置的数,也全部存到alls这个可变数组内。*/ sort(alls.begin(),alls.end());//排序alls里面的所有坐标值alls.erase(unique(alls.begin(),alls.end()),alls.end());//去重并调整里面的坐标值。
/*所有输入的关于位置的数,也就是所谓的坐标,已经排序去重并调整大小了,经过了这两步,得到的是
有序的,且中间没有空位的,新的alls可变数组,这对于后面的离散化是很重要的。*/ for(auto item:add){int x=find(item.first);//找x这个坐标在alls数组里面的数组下标是多少。a[x]+=item.second;//在alls数组里面找到x所在的位置后,就直接执行c的插入操作就可以了。}//插入操作for(int i=1;i<=alls.size();i++) s[i]=s[i-1]+a[i];//注意i<=alls.size(),是从下标1开始的,不是0.
/*这里还是和求前缀和是一样的,在求前缀和之前都要定义一下前缀和的表示,在我看来就是定义一种性质嘛,注意这里是i从1开始,不从0开始是为了避免边界问题。*/for(auto item:query){//这个不一定要写成item,随便写自己喜欢的单词就好,不影响的。int l=find(item.first),r=find(item.second);//分别求l,r在alls数组里面的位置。printf("%d\n",s[r]-s[l-1]);//这就是求前缀和,直接用公式就可以,这是一维前缀和哦。}//查询并求前缀和的操作/*这里面的first,second就是键值,因为我的add和query的vector都是PII类型的,也就是pair<int,int>类型的,就拿这里来说,这里query的item.first指的是输入的l,而item.second指的是输入的r。*/return 0;
}
上面是y总的分析,我觉得分析的挺好的。
以上就是我对于算法里面的离散化的看法与理解,就这样吧。
相关文章:

算法里面的离散化
一、离散化(discretization)在算法和数据结构中指的是将连续的输入数据映射到离散的值或者范围,从而使得处理和计算变得更高效。通常用于处理大范围或者无限可能的输入,以便将其转化为有限的、可以有效处理的范围。 离散化的定义…...

Https AK--(ssl 安全感满满)
免责声明:本文仅做分享! 目录 https探测 openssl Openssl连接服务器获取基本信息 连接命令: 指定算法连接: 测试弱协议连接是否可以连接: 得到的内容包括: sslscan 在线查询证书 https AK type 中间人AK sslsplit 工具…...

ERROR: Failed building wheel for cython_bbox | pip install cython_bbox 失败【解决方案】
🥇 版权: 本文由【墨理学AI】原创首发、各位读者大大、敬请查阅、感谢三连 🎉 声明: 作为全网 AI 领域 干货最多的博主之一,❤️ 不负光阴不负卿 ❤️ 文章目录 win11 系统 pip3 install cython_bbox 失败报错如下解决方法:1 下载…...
逻辑与位运算的双面舞者:、、|、||深度解析
深入解析&、&&、|、||:逻辑与位运算的奥秘之旅 在编程的世界里,&、&&、|、||这四种运算符扮演着至关重要的角色。它们不仅仅是简单的符号,更是连接程序逻辑、实现复杂功能的桥梁。本文旨在深入探讨这四者的区别与联…...

中断门+陷阱门
中断门: 中断描述符在IDT表里面 kd> dq idtr 80b95400 83e48e000008bfc0 83e48e000008c150 80b95410 0000850000580000 83e4ee000008c5c0 80b95420 83e4ee000008c748 83e48e000008c8a8 80b95430 83e48e000008ca1c 83e48e000008d018 80b95440 000085000050…...

RTMP直播播放器的几种选择
如何选择RTMP播放器? 在选择RTMP播放器时,需要综合考虑多个因素,以确保选择的播放器能够满足实际需求并提供良好的用户体验。以下是一些选择RTMP播放器的建议: 1. 功能需求 低延迟:对于直播场景,低延迟是…...

初识爬虫1
学习路线:爬虫基础知识-requests模块-数据提取-selenium-反爬与反反爬-MongoDB数据库-scrapy-appium。 对应视频链接(百度网盘):正在整理中 爬虫基础知识: 1.爬虫的概念 总结:模拟浏览器,发送请求,获取…...

【趣学Python算法100例】兔子产子
问题描述 有一对兔子,从出生后的第3个月起每个月都生一对兔子。小兔子长到第3个月后每个月又生一对兔子,假设所有的兔子都不死,问30个月内每个月的兔子总对数为多少? 题目解析 兔子产子问题是一个有趣的古典数学问题,…...
HTTP 四、HttpClient的使用
一、简单介绍 1、简介 HttpClient是Apache Jakarta Common下的子项目,用来提供高效的、最新的、功能丰富的支持HTTP协议的客户端编程工具包,并且它支持HTTP协议最新的版本和建议。HttpClient已经应用在很多的项目中,比如Apache Jakarta上很著…...
C语言:结构体变量
1. 结构体变量的引用方法 例如,若有数据定义: struct Student{char name[10];int age;struct Date birthday; }s1,s2,stu[10]; 则下面对结构体变量的引用都是正确的: s1.age20; scanf("%d",&s1.age); gets(stu[0].name); s…...
bibtex是什么
BibTeX 是一个用于处理和格式化参考文献的工具,常与 LaTeX 一起使用。它提供了一种方便的方式来管理和生成参考文献列表,特别适用于学术写作和科研论文中。以下是对 BibTeX 的详细介绍: 基本概念 BibTeX 是 LaTeX 的一个附加工具࿰…...

【大模型专栏—进阶篇】智能对话全总结
大模型专栏介绍 😊你好,我是小航,一个正在变秃、变强的文艺倾年。 🔔本文为大模型专栏子篇,大模型专栏将持续更新,主要讲解大模型从入门到实战打怪升级。如有兴趣,欢迎您的阅读。 Ǵ…...
MVC应用单元测试以及请求参数的验证
SpringMVC支持对Controller单元测试 RunWith(SpringJUnit4ClassRunner.class) ContextConfiguration(locations {"classpath:mvc-dispatcher-servlet.xml", }) WebAppConfiguration public class ControllerJUnitBase{Resourceprivate RequestMappingHandlerMappin…...

算法:TopK问题
题目 有10亿个数字,需要找出其中的前k大个数字。 为了方便讲解,这里令k为5。 思路分析(以找前k大个数字为例) 很容易想到,进行排序,然后取前k个数字即可。 但是,难点在于,10亿个数…...
.json文件的C#解析,基于Newtonsoft.Json插件
目录 1. 前言 2. 正文 2.1 问题 2.2 解决办法 2.2.1 思路 2.2.2 代码实现 2.2.3 测试结果 3. 备注 1. 前言 天气晚来秋,这几天天气变凉了,各位同学注意好多穿衣服。回归正题 由于需要,需要将json的配置里面的调理解析出来,做成接口,以便于开发。 2. 正文 2.1 …...

四、(JS)JS中常见的加载事件
一、文档加载监听 (1)抛出疑惑,什么是文档加载监听?为什么要有这个东西? 老样子,我们先讲一个场景,带着大家熟悉为什么会有文档加载监听,是来解决什么问题来着的。 我们先看下这段…...

[网络]https的概念及加密过程
文章目录 一. HTTPS二. https加密过程 一. HTTPS https本质上就是http的基础上增加了一个加密层, 抛开加密之后, 剩下的就是个http是一样的 s > SSL HTTPS HTTP SSL 这个过程, 涉及到密码学的几个核心概念 明文 要传输的真正意思是啥 2)密文 加密之后得到的数据 这个密文…...
React 嵌套类名样式不生效
修改前 父级.blog样式生效,子级.circle样式不生效 // app/blog/page.js import styles from "./page.module.scss"export default function Blog () {return (<div className{styles.blog}><div classNamecircle><div /></div>…...

20Kg载重30分钟续航多旋翼无人机技术详解
一、机架与结构设计 1. 材料选择:为了确保无人机能够承载20Kg的负载,同时实现30分钟的续航,其机架材料需选用轻质高强度的材料,如碳纤维或铝合金。这些材料不仅具有良好的承重能力,还能有效减轻无人机的整体重量&…...
详解c++:认识类
文章目录 前言一、类是什么二、类(class)的使用publicprivate:protected: 前言 C 是一种面向对象的编程语言。面向对象编程是一种编程范式,它使用“对象”来设计软件应用程序。在面向对象编程中,对象包含了…...

怎么让大语言模型(LLMs)自动生成和优化提示词:APE
怎么让大语言模型(LLMs)自动生成和优化提示词:APE https://arxiv.org/pdf/2211.01910 1. 研究目标:让机器自己学会设计提示词 问题:大语言模型(如GPT-3)很强大,但需要精心设计的“提示词”才能发挥最佳效果。过去靠人工设计提示词,费时费力,还可能因表述差异导致模…...
第16节 Node.js 文件系统
Node.js 提供一组类似 UNIX(POSIX)标准的文件操作API。 Node 导入文件系统模块(fs)语法如下所示: var fs require("fs") 异步和同步 Node.js 文件系统(fs 模块)模块中的方法均有异步和同步版本ÿ…...

使用vsftpd搭建FTP服务器(TLS/SSL显式加密)
安装vsftpd服务 使用vsftpd RPM安装包安装即可,如果可以访问YUM镜像源,通过dnf或者yum工具更加方便。 yum -y install vsftpd 启动vsftpd、查看服务状态 systemctl enable vsftpd systemctl start vsftpd systemctl status vsftpd 备份配置文件并进…...
usbutils工具的使用帮助
作为嵌入式系统开发中的常用工具,usbutils 是一套用于管理和调试USB设备的Linux命令行工具集。以下是其核心功能和使用方法的详细说明: 1. 工具组成 核心命令: lsusb:列出所有连接的USB设备及详细信息(默认安装&#…...

8.RV1126-OPENCV 视频中添加LOGO
一.视频中添加 LOGO 图像大体流程 首先初始化VI,VENC模块并使能,然后创建两个线程:1.把LOGO灰度化,然后获取VI原始数据,其次把VI数据Mat化并创建一个感兴趣区域,最后把LOGO放感兴趣区域里并把数据发送给VENC。2.专门获…...
江科大读写内部flash到hal库实现
hal库相关代码 进程结构体 typedef struct {__IO FLASH_ProcedureTypeDef ProcedureOnGoing; /*表示闪存操作过程中的不同状态或过程类型*/__IO uint32_t DataRemaining; /*记录尚未完成的页数或者半字数*/__IO uint32_t Address; /…...

OrCAD X Capture CIS设计小诀窍系列第二季--03.如何在Capture中输出带有目录和元器件信息的PDF
背景介绍:我们在进行原理图设计时,经常需要输出PDF来查看或评审,但通过”Print”功能导出的PDF较为简单,只能查看设计视图;而通过使用Ghostscript软件可以输出带有目录和元器件信息的PDF,让设计师可以直接在…...
gvim比较两个文件不同并合并差异
使用 gvim 比较两个文件的不同: 方式一,使用 gvim 同时打开两个待比较的文件。 比较通用方式是采用 gvim -d 选项,具体命令,如下: gvim -d <file1> <file2>方式二,先用 gvim 打开一个文件&am…...

2025年06月06日Github流行趋势
项目名称:agent-zero 项目地址url:https://github.com/frdel/agent-zero项目语言:Python历史star数:8958今日star数:324项目维护者:frdel, 3clyp50, linuztx, evrardt, Jbollenbacher项目简介:A…...
开源PHP在线客服系统源码搭建教程
在当今数字化时代,在线客服系统已成为企业与客户沟通的重要桥梁。开源PHP客服系统因其灵活性、低成本和高可定制性而受到众多企业的青睐。本文将介绍几款优秀的开源PHP客服系统,并提供详细的搭建教程。 演示网站:gofly.v1kf.com 1.1 主流开源…...