# 离散化
|||离散化就是三句话,sort,unique,lower_bound|||
1.专业术语:把无限空间中有限的个体映射到有限的空间中去,以此提高算法的时空效率。
2.通俗语言:离散化是在不改变数据相对大小的条件下,对数据进行相应的缩小。
3.一些例子:1,999,6,1005;这四个数字离散化后变成1,3,2,4; a[1]=1, a[2]=6, a[3]=999, a[4]=1005; 那么如果是坐标呢?比如(425,5234)(54322,32)(4242423,1)离散化后就成了(3,4)(5,2)(6,1),通常是对x,y分开排序,这里是区间的左界和右界,所以必须结合在一起排序。
4. VOJ1056永远是离散化的经典问题。大意是给定平面上的n个矩形(坐标为整数,矩形与矩形之间可能有重叠的部分),求其覆盖的总面积。平常的想法就是开一个与二维坐标规模相当的二维Boolean数组模拟矩形的"覆盖"(把矩形所在的位置填上True)。可惜这个想法在这里有些问题,因为这个题目中坐标范围相当大(坐标范围为-10^8到10^8之间的整数)。但我们发现,矩形的数量n<=100远远小于坐标范围。每个矩形会在横纵坐标上各"使用"两个值,100个矩形的坐标也不过用了-10^8到10^8之间的200个值。也就是说,实际有用的值其实只有这么几个。这些值将作为新的坐标值重新划分整个平面,省去中间的若干坐标值没有影响。我们可以将坐标范围"离散化"到1到200之间的数,于是一个200*200的二维数组就足够了。实现方法正如本文开头所说的"排序后处理"。对横坐标(或纵坐标)进行一次排序并映射为1到2n的整数,同时记录新坐标的每两个相邻坐标之间在离散化前实际的距离是多少。
5. 1,999,6,1005;这四个数字离散化后变成1,3,2,4就如这个例子,如果要插入555这个数字,需要先将数组排序,然而二分查找到自己应该去的位置。通常用lower_bound(a+1,a+n+1,x)-a;这个的意思就是a数组的长度为n,要插入一个数x,对于给定的已经排好序的a,x最早能插入到那个位置。与此对应的是x最晚能插入的位置就是函数upper_bound(a+1,a+n+1,x)-a; 设a{0,1,2,2,3}然后分别输出lower_bound(a,a+5,2)-a和upper_bound(a+1,a+n+1,x)-a,输出结果为2 4.为什么呢?0,1,||,2,2,3;最早可插入的位置lower,所以返回值为2,再看看upper。0,1,2,2,||,3,因为下标从0开始,所以输出4
int a[10]={0,3,5,7,7,40000}; int s[10]; void lsh(){ int n=5; for(int i=1;i<=n;i++) s[i]=a[i]; sort(s+1,s+n+1); int size=unique(s+1,s+n+1)-s; //返回离散化后的元素个数,已去重 cout<<size<<endl; for(int i=1;i<=n;i++) a[i]=lower_bound(s+1,s+size+1,a[i])-s; for(int i=1;i<=n;i++) cout<<a[i]; //a[i]变成了离散化后的值 //s[a[i]]是a[i]的原值 //输出结果: //5 //12334 }