什么是离散化
离散化就是映射
离散化是一种在程序设计和算法优化中常用的技术,其核心思想是将无限空间中有限的个体映射到有限的空间中去,以此提高算法的时空效率。具体来说,离散化是在不改变数据相对大小的条件下,对数据进行相应的缩小或整合,使得原本稀疏的数据变得相对稠密(在相对位置或值域上)。
离散化的步骤
- 收集待离散化的数据:将所有需要处理的数据收集起来。
- 排序:对收集到的数据进行排序,为后续的去重和映射做准备。
- 去重:去除排序后数组中的重复元素,可以使用 unique 函数来实现。
- 映射:将去重后的数据映射到一个新的连续的整数序列中,常用二分查找的方法来实现快速映射。
- 替换:将原数据替换为映射后的离散化值。
题目示例
题目,来源Acwing
代码 C++
提示:这里可以添加技术细节
// 什么是离散化,离散化就是在一个很大的范围但是使用非常稀疏的数组中,将数组使用到的位置映射到更小的数组。
// 达到节省空间,时间的效果。在这一过程中,最重要的是位置的映射。
// 步骤
// 1. 处理输入
// 2. 将原数组排序,降重,这一步非常关键,包含映射
// 3. 值的插入操作,加和操作,注意是在映射的位置操作
// 4. 构建前缀和数组1
// 5. 输出
#include<iostream>
#include<algorithm>
#include<cstring>
#include<vector>
using namespace std;
int n, m;
const int N = 300010;
// 使用的变量
int a[N], s[N];// 存储原数组,前缀和
vector<int> alls; //存储(所有与插入和查询有关的)坐标
vector<pair<int, int>> add, query; //存储插入和询问操作的数据
// 寻找映射的位置,注意是在alls数组中找,alls存储的是位置信息,x是原来的位置,需要找映射的位置
int find(int x)
{
int i = 0, j = alls.size() - 1;
while(i < j)
{
int mid = (i + j) / 2;
if(alls[mid] >= x) j = mid;
else i = mid + 1;
}
return j + 1;
}
int main()
{
cin >> n >> m;
for(int i = 1; i <= n; i++)
{
int x, c;
cin >> x >> c;
alls.push_back(x);
add.push_back({x, c});
}
for(int i = 1; i <= m; i++)
{
int l, r;
cin >> l >> r;
alls.push_back(l);
alls.push_back(r);
query.push_back({l, r});
}
// 排序与去除重复的位置
sort(alls.begin(), alls.end());
alls.erase(unique(alls.begin(), alls.end()), alls.end());
// 加和操作
for(auto item : add)
{
int l = find(item.first);
a[l] += item.second;
}
// 构建前缀和数组
for(int i = 1; i <= alls.size(); i++)
{
s[i] = s[i-1] + a[i];
}
// 查询
for(auto item : query)
{
int l = find(item.first);
int r = find(item.second);
cout << s[r] - s[l-1] << endl;
}
return 0;
}
小结
离散化的优点包括提高算法效率、简化问题和实现特殊算法 。例如,在处理坐标或区间相关的问题时,通过离散化可以将坐标或区间映射到较小的整数范围内,从而简化问题的求解过程。此外,对于一些由于数据范围过大或数据分布不均匀导致算法难以实现或效率极低的情况,离散化可以使得这些算法得以实现或提高效率。