【学习笔记】离散化

简单。

简单定义

把一些值域很大的正数映射到一个很小的范围内

适用范围

当题目中所给的数据为正数且值域很大(如,([1,10^{19}]))时,如果题目不要求对这些数本身进行操作并且不需要求具体的值,只需要比较它们大小的关系或其它不涉及具体数值的操作,那么可以对这个序列进行离散化处理。

离散化有一个很著名的应用就是用树状数组求逆序对。

具体做法

一个通用的做法是,把原序列复制一份到新序列里,然后把新序列排序后去重,最后通过 lower_bound 函数得到原序列中每个数的排名。

e.g.

原序列:1000 1000 114514 1919 1919 810 114514
复制、排序:810 1000 1000 1919 1919 114514 114514
去重:810 1000 1919 114514
相对排名:2 2 4 3 3 1 4 

参考代码:

#include <bits/stdc++.h>

using namespace std;

int main()
{
	int a[10001],b[10001],n,m;
	cin>>n;
	for(int i=1;i<=n;i++)
	{
		cin>>a[i];
		b[i]=a[i];
	}
	sort(b+1,b+n+1); //排序
	m=unique(b+1,b+n+1)-b-1; //去重
	for(int i=1;i<=n;i++) a[i]=lower_bound(b+1,b+m+1,a[i])-b; //lower_bound函数二分查找大于等于x的第一个位置
	for(int i=1;i<=n;i++) cout<<a[i]<<" ";
	return 0;
}

有时候必须去重,有时候可以不去重

然后还有一种写法,需要搞一个结构体,很麻烦。

掌握这一种写法足以应付这种题目。

原文地址:https://www.cnblogs.com/BlueInRed/p/12404548.html