离散化
title: 离散化
categories:
- ICPC
tags:
- null
abbrlink: 515818b4
date: 2024-08-03 00:00:00
离散化是一种数据处理的技巧,本质上可以看成是一种 哈希,其保证数据在哈希以后仍然保持原来的全/偏序关系。
https://oi-wiki.org/misc/discrete/
通俗地讲就是当有些数据因为本身很大或者类型不支持,自身无法作为数组的下标来方便地处理,而影响最终结果的只有元素之间的相对大小关系时,我们可以将原来的数据按照排名来处理问题,即离散化。
用来离散化的可以是大整数、浮点数、字符串等等。
最常见方法:排序+去重+二分
//数据离散化_排序+去重
void discrete()
{
sort(lan.begin(), lan.end()); //排序
lan.erase(unique(lan.begin(), lan.end()), lan.end()); //去重
}
//查询
int query(int x)
{
return lower_bound(lan.begin(), lan.end(), x)-lan.begin(); //返回所查询的数据的下标
}
函数封装
//函数接受需要离散化的vector和离散化后对应的数从start开始两个参数
//返回的是离散化的结果vector,下标与原来的下标一样,存的值是我们想要的,也是find函数下想要的。
//odata[i]离散化的结果是res[i]
vector<int> discrete(const vector<int>& odata, int start = 0) {
//
const int n = odata.size();
auto copy = odata;//对原数组的拷贝操作
sort(copy.begin(), copy.end());
// 考虑重复值
copy.erase(unique(copy.begin(), copy.end()), copy.end());
vector<int> res(n);
for (int i = 0; i < n; i += 1) {
// lower_bound >= 由于数值本身就存在,因此必然是找到=的情况
res[i] = lower_bound(copy.begin(), copy.end(), odata[i]) - copy.begin() + start;
}
return res;
}
2.借助 map 自动排序
vector<int> discrete(const vector<int>& odata, int start = 0) {
const int n = odata.size();
// C++中的map自带升序效果
// <数值,下标>
map<int, int> autoSort;
for (int i = 0; i < n; i += 1) {
autoSort[odata[i]] = i;
}
//autosort排序后,小数在前面,
vector<int> res(n);
for (auto it = autoSort.begin(); it != autoSort.end(); ++it) {
res[it->second] = start;
start += 1;
}
return res;
}
999在原来的数中排名第15小,它会被映射成15,我们需要保证结果和999这个值没有关系,或者只和相对大小的有关。代入题目例子更容易理解,可以看acwing板子题区间和https://www.acwing.com/problem/content/804/
不需要保序的离散化,可以在线做
//哈希表实现
unordered_map<int, int> S;
int n=0;
int get(int x)
{
if (S.count(x) == 0) S[x] = ++ n;
return S[x];
}
本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来源 爱飞鱼的blog!