离散化(Discretization ),把无限空间中有限的个体映射到有限的空间中去,以此提高算法的时空效率。
通俗的说,离散化是在不改变数据相对大小的条件下,对数据进行相应的缩小。
原数据:1,999,100000,15;处理后:1,3,4,2;
原数据:{100,200},{20,50000},{1,400};
——百度百科
什么时候使用离散化
先看一到例题
给定 n 个数(可能相同)a1,a2…an,出现次数最多的数出现了多少次。(n<= 2*10 ^ 5,0< ai <= 10 ^ 9)
看似一道水题,只要开一个标记数组cnt记录每一个数字出现的次数即可,比如 cnt[a[i]]++。但是值得注意的是,ai可能非常大,这就导致 cnt 数组会开不下,此时,就要用到离散化。
离散化的步骤
本文中离散化的方式主要分两种:
1.使用结构体
步骤:
Ⅰ.开一个结构体数组来记录数的初始值data和在数组中的位置id。
Ⅱ.将结构体数组按初始值大小来排序,可以在结构体里面写了个运算符重载,或者写一个比较函数。
Ⅲ.将排序后的结构体数组中的初始值,依次存到一个rank数组中。
Tip:按原数组source大小排序后,rank[i]就是原数组source中第i大的数,这样一来就将这个数和他是第几大映射起来,第 i 大的数出现一次,只需要 cnt[i]++ 就可以,而 i 一定是小于等于 n 的,数组只需要开到2 * 10 ^ 5就可以了。
这样还会有一个问题:如何找到 i 呢 ,肯定不能通过rank[i] 来找到 i,这里使用将数据的输入顺序 和 排序后的顺序形成映射。
拿开始序言中的例子来分析:
原数据:1,999,100000,15;处理后:1,3,4,2; 将原数据排序后是 1(第1大),15(第2大),999(第3大),100000 (第4大),所以离散化后就是 1,3,4,2 ,source[1] = 1,source[2] = 3,source[3] = 4,source[4] = 2,后一个区间的例子,大家可以自己试试。
代码:
#include <bits/stdc++.h>
using namespace std;
const int Max = 2e5+10;
struct Node{
int data,id;
bool operator < (const Node &a) const {
return data < a.data;
}
}node[Max];
int rank[Max],n,source[Max],cnt[Max];
int ans = 0