数轴弹簧向内强力收缩,将散落极广的超大稀疏空间高保真压缩至超紧凑连续地址
在算法竞赛中,我们经常遇到数值范围极大(如 $X \in [-10^9, 10^9]$),但实际涉及的节点个数 $N$ 却极小(如 $N \le 10^5$)的区间问题。直接以数值作为数组索引开销是完全无法接受的。离散化(Discretization)通过映射,在保持元素原有大小相对大小关系的前提下,将所有大数值压缩成连续的较小数组索引 $[0, N-1]$。
标准的 C++ 离散化流程包含三部曲:
alls 中,执行 sort 升序排列。unique 割除重复元素,保留相对顺序,并擦除尾部垃圾地址。lower_bound 在 $O(\log N)$ 时间内,把原始值 $X$ 映射为其在去重排序后数组中的索引值。💡 弹簧收缩的物理本质: 离散化就如同给数轴装上高弹性弹簧。在保留节点左、中、右大小层级排序的前提下,将松散空洞的大刻度剔除,强力收缩并拢,使得相邻两项物理连续。
999999999),并点击“写入新坐标”添加至原始数轴,接着点击“开始离散化”观摩弹簧物理收缩!vector<int> alls; // 存储所有超大离散坐标值
void discretize() {
// 1. 升序排序
sort(alls.begin(), alls.end());
// 2. 去重,割除冗余元素
alls.erase(unique(alls.begin(), alls.end()), alls.end());
}
// 3. 二分查找获取离散化后紧凑的 0-indexed 索引
int find(int x) {
return lower_bound(alls.begin(), alls.end(), x) - alls.begin();
}