离散化

· · 个人记录

在问题中,我们经常需要把一些数放进下标里操作,如计数排序。

但是,如果问题的值域太大了,我们怎么办?(如 2 \times 10^9

这个时候,就需要离散化。

【离散化】

我们可以把每一个数按顺序映射成一个比较小的数。

比如,a 数组是 2,10,1233,3242434

那么,映射之后就是:

这个映射的过程,就叫做离散化。 ## 【实现】 法一: ### 排序 排序的作用,就是方便我们映射之后快速找到映射关系。 如果我们把所有数映射成了一个有序的连续整数序列,那查询一个数的位置就可以直接用二分查找,非常快捷。 ### 去重 因为原数组中可能有重复元素,但是离散化的映射关系不可能一个数对应很多个数,所以要去重。 ### 寻找 映射完之后,我们要找到原数所对应的映射值。因为已经排过序了,可以用二分查找。 法二: 用map把所有数记录下来,然后遍历一遍,map是自动从小到大遍历的。 法三: 排序,然后从前到后扫一遍,如果和前面不一样就 cur++ 然后赋值。 ------------ 我们发现,以上三步都可以用 STL 代替手写。 排序可以用 sort,去重可以用 unique,寻找可以用 lower_bound。 当然,如果有需要,可以自己手写以修改。 ## 【板子】 法二:(最好写) ``` int a[N]; map<int, int> mp; for (int i = 1; i <= n; i++) { cin >> a[i]; mp[a[i]] = 0; } int cur = 0; for (auto &i: mp) i.second = ++cur; for (int i = 1; i <= n; i++) a[i] = mp[a[i]]; ```