C++怎么实现离散化_C++坐标压缩技巧【算法】

2次阅读

离散化本质是映射,即将稀疏原始值压缩为从0或1开始的连续整数序列;需先收集所有待离散值(含查询点、端点等),排序去重后用lower_bound查坐标,二维需分别处理x、y并独立建映射。

C++怎么实现离散化_C++坐标压缩技巧【算法】

离散化本质是映射,不是排序

离散化真正要解决的,是把一稀疏、可能极大(比如 1e9)或带负数的原始值,压缩成紧凑、从 01 开始的连续整数序列。它不依赖排序本身,但排序是最常用手段——因为只有排好序,才能去重 + 建立下标到值的映射关系。

常见错误是只做 sort + unique,却忘了用 lower_bound 把原值“查回去”。没这一步,离散化就只是扔掉了重复值,没完成坐标压缩。

  • 必须先收集所有待离散的值(包括查询点、端点、修改位置等),不能只对输入数组操作
  • vector 存原始数据,sort 后调用 unique 返回新尾迭代器,再用 erase 真删除
  • 每次查找用 lower_bound(v.begin(), v.end(), x) - v.begin(),结果就是压缩后的坐标

std::lower_bound 的边界行为必须确认

离散化后坐标从 0 开始,但如果你的原始数据里有比最小值还小的数(比如查询时传入非法值),lower_bound 会返回 v.begin(),减出来是 0 —— 这看起来像合法坐标,实则越界。这不是 bug,是设计如此,你得自己兜底。

  • 如果业务要求严格范围检查,查之前加 if (x v.back())
  • 若允许“插入不存在的值”,那 lower_bound 返回的下标就是它该在的位置,直接用没问题
  • 别用 upper_bound 替代,它返回的是第一个大于的下标,会导致相同值映射到不同坐标

重复值必须去重,但去重方式影响稳定性

离散化要求“相同原始值 → 相同压缩坐标”,所以去重不可省。但 unique 只移除相邻重复项,必须配合 sort 才生效;单独 unique 在未排序容器上等于白干。

立即学习C++免费学习笔记(深入)”;

  • 正确顺序: sort(v.begin(), v.end()); auto it = unique(v.begin(), v.end()); v.erase(it, v.end());
  • 不要用 set 替代:虽然自动去重+有序,但插入复杂度高,且无法保证后续 lower_bound 查找效率(set 不支持随机访问迭代器)
  • 若原始数据已部分有序(比如按时间戳追加),仍需全量 sort,不能只 merge,否则 unique 会漏掉非邻接重复

二维坐标压缩要分别处理 x 和 y

遇到点集(如 vector<pair int>></pair>)需要压缩,不能把 xy 拼成一个数再离散——比如 x=1000, y=2x=10, y=200 可能哈希冲突。必须拆开,各自建映射表。

  • 分别提取所有 x 值到 xs,所有 y 值到 ys,各自排序去重
  • 每个点 (x, y) 映射为 (lower_bound(xs.begin(), xs.end(), x) - xs.begin(), lower_bound(ys.begin(), ys.end(), y) - ys.begin())
  • 注意:压缩后二维索引仍是稀疏的,不能直接开二维数组,要用 map<pair>, T></pair> 或哈希表存

离散化最易被忽略的点,是“哪些值该进离散池”——漏掉查询中出现的坐标、区间端点、或者更新目标,压缩后查不到,程序就静默错。宁可多塞几个值,别省那几毫秒排序时间。

text=ZqhQzanResources