AcWing笔记 -- 离散化
前言
所谓离散化,是将给定的有序序列通过二分查找,将其对应的值映射到其对应的序号的过程。如给定一个数组元素[5, 10, 55, 96, 1055464, 546467979],显然这是一个给定长度的有序数组。对于这样一个元素确定的有序数组,离散化之后,5映射为1也就是其序号(映射为0也可以),同理10就映射为2,546467979映射为6。这样操作过后就可以将数据范围较大的离散值映射为数据范围较小的值。
而离散化操作一般适用于这样一种场景。当题目给出的数据范围较大,且要求对一些较大的数据进行维护时,若我们提前开一个大数组的话,可能会导致MLE。但是若数据的个数并不是很多(10^6以下),我们就可以使用离散化将较大的数据映射成其数组下标(即序号,可从0开始或者1开始),从而将范围缩减,需要的数组长度就可以节省。
离散化步骤
1.数据排序与去重
由于我们要求有序的离散化,故要将数据进行排序。而且为了防止冗余的判断,我们要把数据中重复的部分去除掉。
这里使用vector来存储数据,排序加去重的代码如下
//假设存储数据的是 vector<int> A
sort(A.begin(),A.end());
A.erase(unique(A.begin(),A.end()),A.end());
其中unique函数位于algorithm库中,作用是将可迭代对象的多余重复元素都移动到对象的末尾,且返回其头部的迭代器。而erase方法可以将参数位于头尾的元素删去,这样就可以将重复元素去除掉了。
2.二分查找查找对应序号
int Find(int x)
{
int l = -1;
int r = A.size();
while(l+1!=r)
{
int mid = l+r >> 1;
if(A[mid] <= x)
l = mid;
else
r = mid;
}
return l;(返回l代表从0开始编号,返回l+1代表从1开始编号)
}
这段二分模板来源可以看二分模板 不会乱的 - 凪风sama - 博客园 (cnblogs.com)
通过这段二分查找就可以查到输入x离散化后映射的值为几。
最后贴一道例题
离散化