离散化是数据结构中的一个常用技巧,其可以有效的降低时空复杂度,其基本思想就是在众多可能的情况中,只去考虑需要用到的值,通过离散化,可以改进低效的算法,甚至实现根本不可能实现的算法。
对于一些数量较少,但数值较大或者可能出现负数这种难以处理的数据,自身无法作为数组的下标保存对应的属性,如果这时只是需要这些数据的相对属性, 那么可以对其进行重新赋值,即进行离散化处理。
简单来说,对于 n 个数据,当 n 很小而每个数据 a[i] 的数据范围很大时,就可以考虑离散化为更小的值,将他们重新赋值为 [1,n] 之间的数据,从而实现更多的算法。
例如:有 1E5 个数,每个数的大小不超过 1E9,要对这些数进行某些操作(并查集等),那么肯定不能直接开 1E9 大小的数组,但是 1E5 的范围就完全没问题,也就是说,当不需要这些数据具体是多少时,只需要知道他们的相对大小。
离散化分为两种,一种是重复的元素离散化后数值仍相同,一种则是重复的元素离散化后数值不同。
使用 STL+二分 实现离散化,重复的元素数值仍相同,其实质就是利用一个辅助数组将要离散的数据保存下来,然后进行排序去重,最后再用二分将离散数据的位置放回原数组。
注:
例如:对于数组 {6,8,4,9,5,6,7,4},在排序后得到 {4,4,5,6,6,7,8,9},去重后得到 {4,5,6,7,8,9},经过二分后,原序列变为 {3,5,1,6,2,3,4,1}
int temp[N],a[N];
int main(){
int n;
cin>>n;
for(int i=1;i<=n;i++){
cin>>a[i];
temp[i]=a[i];//辅助数组临时存储
}
sort(temp+1,temp+n+1);//排序,便于去重
int len=unique(temp+1,temp+n+1)-temp-1;//去重,len为去重后数组长度
for(int i=1;i<=n;i++)//a[i]即为离散化后的数组
a[i]=lower_bound(temp+1,temp+len+1,a[i])-temp;
}
使用数组实现离散化,重复的元素数值不同,其直接用结构体存储原序列元素的位置,经过排序后将他们重新赋值,最后将结果存放在 rank 数组中。
例如:
此时,rank 数组就是离散化后的值
struct Node{
int val,id;
bool operator < (const Node &rhs)const{//按值排序
return val>n;
for(int i=1;i<=n;i++){
cin>>a[i].val;
a[i].id=i;//记录序号
}
sort(a+1,a+n+1);//按值排序
for(int i=1;i<=n;i++)//进行映射
rank[a[i].id]=i;
}