Loading

【笔记】离散化

一种基本技巧。

思想

离散化的目的:把无限空间中的有限个体映射到有限空间中去,以此提高算法的时空效率。

具体实现方法:在不改变数据相对大小的前提下对数据进行缩小。

例如:

离散化前:192329,999999,0
离散化后:2,3,1
离散化前:{100,200},{200000,50000000},{1,400000}
离散化后:{2,3},{4,6},{1,5}
离散化前:3.5,2.1,5.6,1.2,3.5
离散化后:3,2,4,1,3

适用于值域大、元素数量少,且数值大小仅用于判断大小关系的题目,离散化预处理以使用某些算法求解。

一种基本的离散化流程实现

先排序去重,然后在排序去重过后的数据中查找原数据每一项所处的位置并替换掉原数据。

这两步都可以用 STL 库里的函数来解决。

第一步:去重,使用 Unique 函数

unique 是 c++ STL 库中的函数,包含在 algorithm 头文件中。

功能:将数组中相邻的重复元素去除。

因为只能去相邻的,所以需要先排序。

格式:

unique(起始地址,结束地址)

该函数的返回值是去重后序列的结束地址,因此如果要求去重后序列的长度,直接拿返回值减去起始地址即可。

第二步:找大小关系,使用 Upper_bound 与 Lower_bound 函数

都是 STL 库函数,包含在 algorithm 头文件中。

原理是二分。时间复杂度 \(O(\log n)\)

lower_bound:查找第一个位置,使得目标元素插入数组该位置,数组仍然有序(\(\ge x\) 的最小值的那一位)

upper_bound:查找最后一个位置,使得目标元素插入数组该位置,数组仍然有序(\(\le x\) 的最大值的下一位)

使用方法与 sort 类似。形如 (起始地址,末尾地址,查找元素,比较函数)

默认在升序排序数组中二分。如要作用于降序排序数组中,则需在最后一项写上比较函数 cmp,与 sort 相同。

函数返回值是上述那一位的地址,如需获得下标,需要减去数组地址。直接写数组名称即可。

代码

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int maxn=1e5+10;
int T;
int n;
int a[maxn],b[maxn];
int main(){
	scanf("%d",&T);
	while(T--){
		scanf("%d",&n);	
		for(int i=1;i<=n;i++){
			scanf("%d",&a[i]);
			b[i]=a[i];
		}	
		sort(a+1,a+1+n);
		int len=unique(a+1,a+1+n)-a-1;
		for(int i=1;i<=n;i++){
			b[i]=lower_bound(a+1,a+1+len,b[i])-a;
			printf("%d ",b[i]);
		}
		printf("\n");
		memset(a,0,sizeof(a));
		memset(b,0,sizeof(b));
	}
	return 0;
}
posted @ 2025-12-12 22:49  Seqfrel  阅读(0)  评论(0)    收藏  举报