整数保序的离散化(C/C++)

news2025/8/2 22:13:03

目录

1. 离散化的概念

1.1 离散化的运用思路

1.2 离散化的方法

1.2.1 排序

 1.2.2 确定一个元素离散化后的结果

1.3 案例分析

1.3.1

 1.3.2 区间和 (来源:Acwing)


1. 离散化的概念

离散化,把无限空间中有限的个体映射到有限的空间中去,以此提高算法的时空效率。
例如:
原数据:1,999,100000,15;

处理后:1,3,4,2;
原数据:{100,200},{20,50000},{1,400};
处理后:{3,4},{2,6},{1,5};

1.1 离散化的运用思路

以下离散化均指整数保序的离散化。

根据离散化的定义,我们能够发现需要如果数据需要做离散化的处理,那么该数据的值域跨度是非常大的,但是分布很稀疏。因为值域的跨度相当大,自身并不能作为数组的下标保存对应的属性。但是如果只需要这些数据的相对属性,那么就可以对数据进行离散化处理。

1.2 离散化的方法

这里只讲常用的方法:重复元素离散化的结果相同。

我们只需要确保两个事情不变:

首先:保证离散化之后的数据尽可能地小而且非负。

其次:离散后的数据要保持原本的大小关系,原本相等的也要保持相等,否则就是错误的离散。

因此,找出原数据在序列中的序位 (可以直接理解为排第几) 就是离散化的关键。

1.2.1 排序

离散化就是确定找出原数据在序列中排第几嘛,因此我们直接对其排序就好了,排完序便可直接根据该数据所在位置的下标确定其离散化的结果。但是显然单单排序是不够的,如果原数据中有重复元素,那么相同的数据就会有不同的离散化结果,这是不被允许的。因此,对排好序的数组我们还要进行去重的操作。

假设原数组为 array。

对于C++:排序用sort,去重用unique,删除末尾重复的元素用erase,即:

array.erase(unique(array.begin(), array.end()), array.end())

 对于C语言:用 qsort 排序,用双指针算法去重就行。

 1.2.2 确定一个元素离散化后的结果

比如:将数据:1 5 3 2 2 3,进行排序,去重,删除后,得到结果:1 2 3 5,比如我们想要知道 5 离散化后的结果是多少,该怎么做呢?答案就是二分查找哦。5 对应的下标就是 5 离散化的结果。这里就是标准的二分查找模板。

二分查找请参考:http://t.csdn.cn/CVAGj

int binary_search1(int* nums, int numsSize, int target)
{
	int l = 0, r = numsSize - 1;
	while (l < r)
	{
		int mid = l + r >> 1;
		if (nums[mid] >= target)
		{
			r = mid;
		}
		else
		{
			l = mid + 1;
		}
	}
	return l;
}

1.3 案例分析

1.3.1

题目描述:

现有数列 A1,A2,A3 ··· ,An,数列中可能有重复元素。现在要求输出该数列的离散化数列,重复元素离散化后的数字相同。

输入:

第一行,一个整数 n (1 <= n <= 10 ^ 5)

第二行,n个整数整数,每个整数的取值为:[-10^9, 10^9]。

输出:

一行,包括 n 个整数。表示数列对应的离散化数列,重复元素离散化后的数字相同。

样例输入:

6

1 23424 242 65466 242 0

样例输出:

1 3 2 4 2 0

int binary_search1(vector<int>& nums, int target)
{
	int l = 0, r = nums.size() - 1;
	while (l < r)
	{
		int mid = l + r >> 1;
		if (nums[mid] >= target)
		{
			r = mid;
		}
		else
		{
			l = mid + 1;
		}
	}
	return l;
}


int main()
{
	vector<int> array;
	vector<int> a;

	int n;
	cin >> n;
	int num;

	for (int i = 0; i < n; i++)
	{
		scanf("%d", &num);
		array.push_back(num);
		a.push_back(num);

	}
	//排序
	sort(array.begin(), array.end());
	//去重和删除
	array.erase(unique(array.begin(), array.end()), array.end());

	for (int i = 0; i < a.size(); i++)
	{
		int ret = binary_search1(array, a[i]);
		cout << ret << " ";
	}
	cout << endl;

	system("pause");
	return 0;
}

 1.3.2 区间和 (来源:Acwing)

假定有一个无限长的数轴,数轴上每个坐标的数都是0.

现在我们首先进行 n 次操作,每次操作将某一位置 x 上的数加上 c 。

接下来,进行 m 次询问,每个询问包含两个整数 l 和 r,你需要求出在区间 [l, r] 之间所有数的和。

输入格式:

第一行包含两个整数 n 和 m。

接下来 n 行,包含两个整数 x 和 c。

再接下来 m 行,每行包含两个整数l 和 r。

输出格式:

共 m 行,每行输出一个询问中所求的区间内数字和。

数据范围:

-10 ^ 9 <= x <= 10 ^ 9 ,

1 <= n , m <= 10 ^ 5 ,

-10 ^ 9 <= l <= r <= 10 ^ 9 ,

-10000 <= c <= 10000

const int N = 300010;

//这里用来存在c的位置加上x 和每一次询问的区间,当然也可以用结构体
typedef pair<int, int> PI;

//在x的位置加上c不止一次,数组存
vector<PI> add;
//询问的区间不止一次,数组存
vector<PI> query;
//存所有添加的值c,需要离散化
vector<int>alls;
//保存离散化后的结果
int a[N];
//求区间和会用到前缀和的,创建一个前缀和数组
int s[N];


int n, m;

//这里离散化的值是从1开始的,为了对应求前缀和时也是从1开始
int binary_search1(int target)
{
	int l = 0, r = alls.size() - 1;
	while (l < r)
	{
		int mid = l + r >> 1;
		if (alls[mid] >= target)
		{
			r = mid;
		}
		else
		{
			l = mid + 1;
		}
	}
	return l + 1;
}


int main()
{

	cin >> n >> m;
	
	for (int i = 0; i < n; i++)
	{
		int x, c;
		cin >> x >> c;
		//记录每一次添加的位置和值
		add.push_back({ x,c });
		//加上c的位置x是需要离散化的
		alls.push_back(x);
	}

	//m次询问
	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);
	}
	
	//排序,去重,删除
	sort(alls.begin(), alls.end());
	alls.erase(unique(alls.begin(), alls.end()), alls.end());

	for (pair<int, int> i : add)
	{
		//将x位置加上c的x进行离散化
		int x = binary_search1(i.first);
		//a数组中的下标就代表离散化的值哈,值代表x的位置
		a[x] += i.second;
	}

	//前缀和处理
	for (int i = 1; i <= alls.size(); i++)
	{
		s[i] = s[i - 1] + a[i];
	}

	//处理询问
	for (pair<int, int> i : query)
	{
		int l = binary_search1(i.first);
		int r = binary_search1(i.second);

		cout << s[r] - s[l - 1] << endl;
	}

	return 0;
}

 

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

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

相关文章

机房信息牌系统

产品特色&#xff1a; 无线低功耗安装简单&#xff0c;快速布置易于维护墨水屏显示&#xff0c;清晰&#xff0c;更环保信息后台推送&#xff0c;远程管理多模版样式随意制作多尺寸&#xff1a;4.2寸&#xff0c;7.5寸&#xff0c;10.2寸4.2寸7.5寸10.2寸标签特性&#xff1a;…

每日一个小技巧:教你如何使用终端工具给你的电脑发送弹窗提醒

现在人手一部智能手机&#xff0c;这些智能手机都有个非常实用的功能&#xff0c;那就是弹窗提醒。当我们收到短信&#xff0c;或者微信信息时&#xff0c;手机就会弹窗显示信息的大致内容。有了这个功能你就不会错过重要信息了。 电脑上也有类似的功能&#xff0c;也很实用。…

改进YOLO系列 | 添加轻量化Decouple_Head 和 ASFF_Head

绿色为ASFF_Head,浅蓝色Decoupled_Head,深蓝色是第三步加的_initialize_dh_biases方法后的效果。 参数量与计算量对比 模型参数量 parameters计算量GFLOPsyolov5s_Head723538916.5ASFF_Head1267484725.0Decoupled_Head892869722.0结构图 本篇介绍的这个Decouple_Head和YOLOX…

亚马逊、temu、速卖通、eBay如何提高店铺的订单数量?有什么技巧?

亚马逊卖家店铺的排名与店铺的订单数量有很大关系&#xff0c;所以卖家必须尝试改善店铺的销售。如果找不到正确的方法&#xff0c;订单速度很慢&#xff0c;卖家应该如何提高店铺的订单数量&#xff1f; 一、选择价格低、流量大的产品 无论是精细操作还是配送模式操作&…

代码随想录 NO51 | 动态规划_leetcode583. 两个字符串的删除操作 72. 编辑距离

动态规划_leetcode583. 两个字符串的删除操作 72. 编辑距离 编辑距离总结动态规划快结束了&#xff0c;时间过的好快啊&#xff0c;今天编辑距离系列结束&#xff01; 583. 两个字符串的删除操作 给定两个单词 word1 和 word2 &#xff0c;返回使得 word1 和 word2 相同所需的…

python使用requests提交post请求并上传文件(multipart/form-data)

目录 一、背景 二、请求接口上传文件 2.1、分析接口 2.2、python进行请求 三、总结 一、背景 也是前几天&#xff0c;有一个需求上传文件需要自动化。具体是上传到系统一个文件&#xff0c;并收到返回结果。考虑使用python的requests&#xff0c;一般这种查询或上传文件的接…

DMotion - 基于DOTS的动画框架和状态机

【博物纳新】专栏是UWA旨在为开发者推荐新颖、易用、有趣的开源项目&#xff0c;帮助大家在项目研发之余发现世界上的热门项目、前沿技术或者令人惊叹的视觉效果&#xff0c;并探索将其应用到自己项目的可行性。很多时候&#xff0c;我们并不知道自己想要什么&#xff0c;直到某…

Android反射@hide API 方法、变量,支持Android11和Android12

Android源码中现在有大量的方法和变量被hide所修饰&#xff0c;而这些被hide修饰的方法和变量是不允许应用层进行反射获取的&#xff0c;所以富有探索精神的程序员们就开始想尽各种办法绕过系统hide限制来使用hide修饰的方法和变量。1、套娃&#xff08;适配Android10即之前&am…

Python实现贝叶斯优化器(Bayes_opt)优化Catboost分类模型(CatBoostClassifier算法)项目实战

说明&#xff1a;这是一个机器学习实战项目&#xff08;附带数据代码文档视频讲解&#xff09;&#xff0c;如需数据代码文档视频讲解可以直接到文章最后获取。1.项目背景贝叶斯优化器(BayesianOptimization) 是一种黑盒子优化器&#xff0c;用来寻找最优参数。贝叶斯优化器是基…

PHPExcel 表格设置

4.5.3。通过行和列设置单元格值 通过设置坐标单元格值可以使用工作表的setCellValueByColumnAndRow方法来实现。 //设置单元格B8 $objPHPExcel->getActiveSheet()->setCellValueByColumnAndRow(1, 8, ‘Some value’); 4.5.4。由列和行中检索的小区 检索的小区的值&#…

Blender——竹篮的制作

效果图前言参考视频&#xff1a;Blender 竹篮建模编制效果3D教程建议Blender版本在v3.0.0或以上&#xff0c;本实验的blender为v3.4.1操作步骤打开一个【常规项目】。点击shading下拉列表&#xff0c;将颜色改为【随机】&#xff0c;背景改为【世界坐标】&#xff0c;勾选【Cva…

Linux期末考试应急

Linux期末考试应急 虚拟机添加硬盘、分区、格式化、挂载、卸载 fdisk -l#查看系统现有分区fdisk <指定磁盘>#指定磁盘分区sudo mkfs.ext3 <指定分区>#格式化磁盘###挂载磁盘1.新建一个目录sudo mkdir /mnt/test2.将指定分区挂载到对应目录sudo mount /dev/sdb10 /…

里程计(一) 数学模型及STM32实现

一、首先确保接线和硬件没问题&#xff0c;并确定控制逻辑 测试单片机-驱动板-电机连线是否接通&#xff1a;控制板IN1,IN2一个接3.3V一个接GND,ENA1接3.3V测左电机&#xff1b;控制板IN3,IN4一个接3.3V一个接GND,ENA2接3.3V测右电机。 在电机已经安装完毕的情况下&#xff0c;…

SAP ABAP中的数据类型 Data Types

简单来说分两种&#xff1a; 数据字典里定义的在ABAP程序里定义的 文章目录1. ABAP数据字典里的1.1 数字型的1.2 字符型1.3 字节型1.4 特殊类型2. 预定义的ABAP数据类型2.1 预定义数字型2.2 预定义字符型2.3 预定义字节型1. ABAP数据字典里的 1.1 数字型的 用在数学计算里的…

IP、MAC和端口号——网络通信中确认身份信息的三要素

目录 &#x1f30f; IP地址 &#x1f30f; MAC地址 &#x1f30f; 端口号 IP、MAC和端口号——网络通信中确认身份信息的三要素 在茫茫的互联网海洋中&#xff0c;要找到一台计算机非常不容易&#xff0c;有三个要素必须具备&#xff0c;它们分别是 IP 地址、MAC 地址和端口…

【Galois工具开发之路】关于ClassFileTransformer的注意点

关于ClassFileTransformer 该接口是javaagent的 Instrumentation.addTransformer 方法的入参之一&#xff0c;用于给加载的类添加一个类转换器&#xff0c;确保在类进入main方法之前&#xff0c;对类进行字节码插桩。 接口函数说明 该接口只有一个方法&#xff0c;即 byte[…

[SSD固态硬盘技术 19] 谁是数据的守护神? 盘内RAID1/RAID5图文详解_盘内数据冗余保护

版权声明&#xff1a; 付费作品&#xff0c;禁止转载前言提到冗余保护&#xff0c;最容易想到的就是RAID(Redundant Arrays of Independent Disks) , 独立冗余磁盘阵列。它是一种把多块独立的物理硬盘按不同方式组合形成一个硬盘组&#xff0c;以此提供比单个硬盘更高的存储性能…

华为OD机试题,用 Java 解【TLV 解码】问题

最近更新的博客 华为OD机试 - 猴子爬山 | 机试题算法思路 【2023】华为OD机试 - 分糖果(Java) | 机试题算法思路 【2023】华为OD机试 - 非严格递增连续数字序列 | 机试题算法思路 【2023】华为OD机试 - 消消乐游戏(Java) | 机试题算法思路 【2023】华为OD机试 - 组成最大数…

数据库浅谈之 LLVM

数据库浅谈之 LLVM HELLO&#xff0c;各位博友好&#xff0c;我是阿呆 &#x1f648;&#x1f648;&#x1f648; 这里是数据库浅谈系列&#xff0c;收录在专栏 DATABASE 中 &#x1f61c;&#x1f61c;&#x1f61c; 本系列阿呆将记录一些数据库领域相关的知识 &#x1f3c…

【CJSON】嵌入式芯片上基于USB HOST的CJSON文件库移植与应用

一 CJSON简介项目遇到了一个需求&#xff0c;就是需要通过U盘或者其他外接设备&#xff0c;与板子&#xff08;嵌入式芯片使用的是LPC1857&#xff09;进行交互。交互的形式有两种&#xff1a;一种是预存在外接U盘中的配置信息CFG&#xff0c;接上U盘之后&#xff0c;嵌入式芯片…