坐标离散化

坐标离散化是一种常见的技巧,对于一些数据量特别大的题目往往有奇效。

举个例子,你需要对输入的 n (n <= 1e5)个数进行标记,每个数标记一下(visit[i] = 1),但是如果对于每一个输入的数字 ai <= 1e18,我们就没办法去建立一个长度为1e18的数组,(当然可以用 set 或者 map),但是其实我们在存放这些数据的时候根本用不到那么大的数组,我们可以对数组的每一个数字编一个对应的编号(从1 到 n),通过编号可以查询到对应的值,通过值也可以获取编号,这样我们可以通过一个长度为 n 的数组去实现。

对于这样一个例子

1 5  8 4 7

根据每个数字的相对大小编号,就变成了下面的样子

1 3 5 2 4

方法其实很简单,首先输入数据,将数据保存在另一个数组中,对其中任一个数组排序 + 去重,通过对未排序的数组的每个值在已经排序的数组中二分查找位置,就可以得到该值在原序列中的相对大小,如果有重复的元素,那么他们的相对大小一定相同,我们把重复的元素去掉了,因此保证排完序的数组中每个值都是唯一的。

通过值可以用二分获取编号,通过编号可用已排序的数组获取值

#include <cstdio>
#include <iostream>
#include <cstring>
#include <algorithm>
using namespace std;
int a[1100];
int b[1100];
int c[1100];
int len;
int getid(int n){
	return lower_bound(a + 1, a + len + 1, n) - a;
}
int main()
{
	for (int i = 1; i <= 5; i++){
		cin >> a[i];
		b[i] = a[i];
	}
	sort(a + 1, a + 1 + 5);
	len = unique(a + 1, a + 6) - a - 1;
	for (int i = 1; i <= 5; i++){
		c[i] = getid(b[i]);
	}
	for (int i = 1; i <= 5; i++)cout << c[i] << " ";
	return 0;
}

 

posted @ 2019-08-06 11:20  correct  阅读(124)  评论(0)    收藏  举报