我一直以为我写过这篇博客了,直到后来。。。。
先介绍一下离散化
我没有系统的学过离散化,不过以我的理解就是将一个数值之间相差比较大的数组即类似max - 次max > 1的数组转化成max - 次max = 1的数组,也就是当数组中数的数值对算法影响不大,但是大小关系影响较大的时候,我们把他们的大小关系用相差1的数表示。
举个例子:
a数组: 99 55 68 47 100 2888888888
离散化后得b数组
b数组: 4 2 3 1 5 6
可以看出数值范围就小了许多但是对应下标的各项大小关系是不变的。
用到的函数
sort
排序函数,很常见的函数,作用是让a数组具有单调性,好用下一个函数
unique(去重)
顾名思义,不同,就是不同的留下,相同的消失,该函数会去掉数组中重复出现的数值,只留下第一次出现的数值。
x
=
u
n
i
q
u
e
(
a
+
1
,
a
+
n
+
1
)
−
a
−
1
,
x = unique(a + 1, a + n + 1)- a - 1,
x=unique(a+1,a+n+1)−a−1,x为去重后a数组的长度。 关于大于x后面的数还有一些规则(我忘了qwq)
当然,unique需要在数组有序的情况下使用
lower_bound
这个就是这篇离散化最重要的函数的,他会返回查询数组中第一个大于等于查询数值的位置的迭代器或指针
比如一个a数组
x
m
=
l
o
w
e
r
b
o
u
n
d
(
a
+
1
,
a
+
n
+
1
,
m
)
−
a
xm = lower_bound(a + 1, a + n + 1, m) - a
xm=lowerbound(a+1,a+n+1,m)−a 此时xm的值就是a数组中第一个大于等于m的数的下标。
方法
需要两个数组, 这里用a, b两个数组,
还有两个变量,这里用n, x。
a数组是读入的原数组,b数组是离散化后的数组。
n记录的是需要读入的数组长度,x记录的是去重后数组的长度。
那么①:读入n, 读入a, 同时令b[i] = a[i];
②对a进行排序,使a有序
s
o
r
t
(
a
+
1
,
a
+
n
+
1
)
sort(a + 1, a + n + 1)
sort(a+1,a+n+1)
③对a去重,同时记录去重后长度
x
=
u
n
i
q
u
e
(
a
+
1
,
a
+
n
+
1
)
−
a
−
1
x = unique(a + 1, a + n + 1) - a - 1
x=unique(a+1,a+n+1)−a−1
④使用lower_bound在长度为x的a数组中对b[i]进行查询, 并使b[i] = 查询出的下标
这一步需要详细说明:
a数组目前是被我们处理过的数组,长度为x且严格单调递增,并包含了所有在原数组中出现过的数值,
那么我们在用b数组查询时,第一个大于等于的b[i]的一定是b[i]本身,因为在b[i]数值出现之前a中没有大于b[i] 的数
同时a中数值在a中的下标能体现该数值在所有数值中的大小排名,所以就是离散化出的数值。
⑤使用b数组
代码
#include<bits/stdc++.h>
#define MAXN 1000010
using namespace std;
int a[MAXN], b[MAXN];
int x, y;
int n;
int main()
{
scanf("%d", &n);
for(int i = 1; i <= n; ++i){
scanf("%d", &a[i]); b[i] = a[i];
}
sort(a + 1, a + n + 1);//排序
x = unique(a + 1, a + n + 1) - a - 1;//去重并记录
for(int i = 1; i <= n; ++i){
b[i] = lower_bound(a + 1, a + x + 1, b[i]) - a; //查询并赋值
}
for(int i = 1; i <= n; ++i)//输出
printf("%d ", b[i]);
puts("");
return 0;
}