离散化详解及应用

技巧

  • 离散化
    • 第一种
    • 第二种

离散化

第一种

  离散化就是把一种离散的数据从新分配。这种离散的数据往往是数据区间很大,有时还会存在负数。在这种情况下,如果每个数据元素的具体值并不重要,重要的是他们之间的大小关系的话,我们可以先对这些数据进行离散化,使数据中的最大值尽可能小且保证所有数据都是正数。
  例如:有这样一个长为6的序列:102131511、123、9813186、-611、55、123,我们可以使序列离散化成5、3、4、1、2、3;使各元素之间的大小关系没有变化。
  离散化的结果保证了数据非负尽可能小,数据之间的大小关系保持不变
算法的过程:

  1. 复制原序列,按升序进行排序。
  2. 去掉序列中重复的元素。
  3. 二分查找原序列在新序列中对应的位置,作为原序列的值,原序列和新序列形成离散化后的映射关系。

例如:对序列105 、35、35、79、-7。排序去重后-7、35、79、105。此时形成映射关系105->4、35->2、35->2、79->3、-7->1。

int n, a[maxn], t[maxn];
//这里以下标1为序列的起点,一般情况下从0开始也可以
for(int i = 1;i <= n;i++)
{
    scanf("%d", &a[i]);
    t[i] = a[i];//t是一个临时数组,用来得到离散化的映射关系
}
//下面使用了STL中的sort(排序),unique(去重),lower_bound(查找)函数
sort(t + 1, t + n + 1);//排序
int m = unique(t + 1, t + 1 + n) - t - 1;//去重,并获得去重后的长度m
for(int i = 1;i <= n;i++)
{
    a[i] = lower_bound(t + 1, t + 1 + m, a[i]) - t;//通过二分查找,快速地把元素和映射对应起来
}

  时间复杂度:O(nlogn)
  注意:如果对边离散化,需要在边距离大于1的两点新增一个点。
例题:POJ 2528 [一维海报]
题解:待补······

第二种

  很好理解的一种离散化,对原数组标记排序,然后离散化放入rank[]数组。
  例如:序列17、100、96、-4、7。标记为1、2、3、4、5。rank[]数组为3、5、4、1、2。即17排在第3大、100排在第5大等等。

#include
struct Node {
	int data , id;
	bool operator < (const Node &a) const {
		return data < a.data;
	}
};
Node num[MAXN];
int rank[MAXN] , n;
for(int i=1; i<=n; i++) {
	scanf("%d",&num[i].data);
	num[i].id = i;
}
sort(num+1 , num+n+1);
for(int i=1; i<=n; i++)
	rank[num[i].id] = i;

你可能感兴趣的:(技巧)