1.什么是离散化?
这是一种处理数据的算法,是使用有序数组中数的下标来映射数,使得一个较小的数可以代指一个叫大的数,常用于当问题给出的数据数据范围特别大,容易导致数组过大不好存储以及引起超时的问题,但同时给出数据的量却又不大时,便可以使用离散化算法来处理数据。
2.离散化算法的一个常用模板?
在这里我将给出一个离散化算法的常用模板,事实上还有很多模板,但它们的思想是相同的,可以选择自己喜欢的模板来使用。
#include <iostream>
#include <algorithm>
#include <unordered_map>
using namespace std;
const int N = 1e5 + 10;//随便给了一个数据范围
//a[i]来记录所有数据
int a[i];
//离散化相关的数组和变量
int pos;//记录离散化数组中有多少值
int disc[N];//离散化数组
unordered_map<int,int> id;//用一个哈希表存储离散化前和后的数据的对应关系
int main()
{
//输入一组值,个数为n
int n = 0; cin >> n;
for(int i = 1;i <= n;i++)
{
cin >> a[i];
disc[++pos] = a[i];
}
//离散化
//先排序
sort(disc + 1,disc + pos + 1);
int cnt = 0;//用来记录离散化数组中不重复的数的个数
for(int i = 1;i <= pos;i++)
{
int x = disc[i];
if(id.count(x)) continue;
id[x] = ++cnt;
}
//处理输出
for(int i = 1;i <= n;i++) cout << id[a[i]] << " ";
3.两道例题,由于主要都是模板的使用,这里只分析算法思想
例一:
数据范围:10≤N≤10000000,1≤M≤1000,1≤Ai≤Bi≤10000000
在看到本题目时,首先可以进行模拟,给出Ai,Bi时,便可以遍历数组中的对应部分,修改数组中的值即可,但麻烦的是,数据范围中Ai,Bi严重超出了数组的范围,遍历时一定会造成超时,此时我们就对本题中的数据做离散化处理,需要注意的是,由于离散化处理之后有的A,B范围会被压缩,导致原本不会被覆盖的部分被覆盖,造成答案错误,所以每有一个数字需要进行离散化,我们将比它大1的数字也进行离散化,这样就可以避免上面这种问题的发生。
例二:
数据范围:1≤n≤2×10^4,−2^31≤a<b<2^31
看到本题时,首先想到的算法是利用差分数组对时间复杂度进行优化,但由于数据范围过大,数组不够开,所以我们要先对数据做离散化处理再进行差分算法的使用,需要注意的是,本题在最后部分需要用一个数组的下标来找回原来的数字是多少,所以我们要修改一下离散化模板,我们要在排序之后进行一下去重处理,调用一下unique函数,它的参数和sort是一样的,这样就可以处理掉这个问题。
4.结语:
这就是离散化算法的全部内容了,欢迎各位于晏、亦菲和我一起交流学习。
5.注意:
在上面两道题目的解释中,我们可以发现,其实直接使用离散化算法是经常会引起错误情况出现的,所以在使用模板时,我们要多加考虑,这样才能避免错误。