离散化看过好几次, 但是过不来多久就忘了, 所以记录一下。
原理当题目的数据量较数据范围要小的时候采用离散化思想达到优化。
比如在数轴上有这些点: 1 000 000, 10, -1000, 1000, 20 000, 10
30 000.
这些点的个数很少, 但是范围却非常大, 如果要求某个区间上的和开的数组
会非常大,所以先对数据进行离散化处理, 离散化其实就是做一个映射, 把
较大数映射成较小数, 然后通过二分来找到这个映射值, 如果用函数表示, 就
是ind = f(val) val表示要映射的较大数, 而 ind 就是映射值, 而一般这个映射
值就是映射数组的下标。
比如上面那个例子, 离散化的过程如下:
- 先对所有数进行排序, 得到的结果为 -1000, 10, 10, 1000, 20 000,
30 000, 1 000 000 - 在另一个数组mark中, 依次存下这些值。
mark[] = {-1000, 10, 10, 1000, 20 000, 30 000, 1 000 000} - 对mark数组进行去重, 因为映射值只会有一个。 这一步和上一步在C++
的代码里就是一句 erase(unique(mark.begin(), mark.end()), mark.end());
上面就是离散化的过程, 后面就是怎么使用这个映射了。
首先我们定义一个find函数, 它其实就是一个二分来找位置, 这里选择用
C++中的lower_bound(), 具体定义:
int find(int val) {
return lower_bound(mark.begin(), mark.end(), val) - mark.begin();
}
lower_bound是返回数组第一个大于等于val的迭代器(相当于一个指针), 然后减去第一个元素的迭代器就是下标了。
最后附上一道acWing上的模板题: 假定有一个无限长的数轴,数轴上每个坐标上的数都是 0。 现在,我们首先进行 n 次操作,每次操作将某一位置 x 上的数加 c。 接下来,进行 m 次询问,每个询问包含两个整数 l 和 r,你需要求出在区间 [l,r] 之间的所有数的和。 输入格式 第一行包含两个整数 n 和 m。 接下来 n 行,每行包含两个整数 x 和 c。 再接下来 m 行,每行包含两个整数 l 和 r。 输出格式 共 m 行,每行输出一个询问中所求的区间内数字和。 数据范围 −109≤x≤109, 1≤n,m≤105, −109≤l≤r≤109, −10000≤c≤10000 输入样例: 3 3 1 2 3 6 7 5 1 3 4 6 7 8 输出样例: 8 0 5
#include#include #include #include #include



