OI-tips 离散化
离散化
离散化,一个很简单却很常用的小技巧。
引入
给你
个数,输出每种数出现的个数,满足 , 。
是不是看上去很简单,直接开一个数组记录个数不就行了。
不过值域的范围是
实现
理解了思想,我们再去考虑如何实现。
map 实现
STL 容器中的 map 是蒟蒻们实现离散化的好帮手,它出现的意义本身就是映射:将某种类型的某值映射到某种类型的某值上。
上面提到的“某种类型”可以是 c++ 中的任意数据类型,当然最常用的就是 int 转到 int,即我们的离散化操作。
关于 map 容器我浅讲一点,有兴趣可以自行学习。
定义方法
map 位于 std 库中,若没有在前面声明 using namespace std
,需要这样定义(下面均为未声明情况):
std::map<int,int>mp;
// </*原数据类型*/,/*映射后数据类型*/>
使用方法
很简单,就和普通的数组一样。
int a=1000000000;
mp[a]=1;
// 将 a 的值映射为 1
例题实现
#include<bits/stdc++.h>
int n,tot,a[1000005],sum[1000005];
bool vis[1000005];
std::map<int,int>mp;
int main()
{
scanf("%d",&n);
for(int i=1;i<=n;i++)
{
scanf("%d",&a[i]);
if(!mp[a[i]]) mp[a[i]]=++tot;
// 离散化
sum[mp[a[i]]]++;
}
for(int i=1;i<=n;i++)
{
if(vis[mp[a[i]]]) continue;
vis[mp[a[i]]]=1;
printf("%d %d\n",a[i],sum[mp[a[i]]]);
}
return 0;
}
优化
可以将 map
换成 unordered_map
,会有一点加速效果。
数组实现
众所周知,stl 容器的速度都比较玄学,因此在面对需要大量运用离散化时,我们需要一种较稳定的实现方法。
回归主题,我们思考一下,离散化的本质是什么?是去重。stl 算法中存在一个操作 unique
,作用是去除容器中相邻的重复元素,好像跟我们的目的很像,但发现其去重的对象只是相邻元素,于是我们在去重前需要先将原序列排序。这就有了离散化=排序+去重的说法。
这样离散化后的数据还能反映数值的大小关系,这就大大增强了这种方法的泛用性。
注意: 由于我们改变了序列的顺序,我们获取每个元素离散化后的值时需要用到 lower_bound 操作,如果原来元素的值对后续没有影响,这个操作最好在离散化后立即进行。(不然像我一样用的时候再查就直接给复杂度乘了一个
for(int i=1;i<=n;i++) b[i]=a[i];
tot=n;
sort(b+1,b+1+tot);
tot=unique(b+1,b+1+tot)-b-1;
for(int i=1;i<=n;i++) a[i]=lower_bound(b+1,b+1+tot,a[i])-b;
例题实现
#include<bits/stdc++.h>
int a[1000005],b[1000005],num[1000005],n,tot;
bool vis[1000005];
int main()
{
scanf("%d",&n);
for(int i=1;i<=n;i++) scanf("%d",&a[i]),b[i]=a[i];
tot=n;
sort(b+1,b+1+tot);
// 先排序
tot=unique(b+1,b+1+tot)-b-1;
// 再去重,tot 直接赋值为不重复的数的个数
for(int i=1;i<=n;i++)
{
int id=lower_bound(b+1,b+1+tot,a[i])-b;
num[id]++;
}
for(int i=1;i<=n;i++)
{
int id=lower_bound(b+1,b+1+tot,a[i])-b;
if(vis[id]) continue;
vis[id]=1;
printf("%d %d\n",a[i],num[id]);
}
return 0;
}
末
离散化虽然基础,但细节也挺多的。
操作难度 | 时间复杂度 | 空间复杂度 | |
---|---|---|---|
map | 简单 | - | |
数组 | 不难 |
不过实测下来还是数组更快一点,因为每次引用 map 都是
本文代码全部线上手打,有问题请指出,感谢支持。
完结撒花~
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· 开发者必知的日志记录最佳实践
· winform 绘制太阳,地球,月球 运作规律
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· Manus的开源复刻OpenManus初探
· 写一个简单的SQL生成工具
· AI 智能体引爆开源社区「GitHub 热点速览」