【题目来源】
https://www.luogu.com.cn/problem/B3694
【题目描述】
给定一个长度为 n 的数列 a。定义 rank(i) 表示数列 a 中比 ai 小的不同数字个数再加一。
对 1≤i≤n,现在请你求出所有的 rank(i)。
【输入格式】
输入的第一行是一个整数,表示数据组数 T。接下来依次给出每组数据的信息:
第一行是一个整数,表示数列长度 n。
第二行有 n 个整数表示数列 a,第 i 个整数表示 ai。
【输出格式】
对每组数据,输出一行 n 个整数,用空格隔开,依次表示 rank(1) 到 rank(n)。
【输入样例】
3
3
1 2 3
5
1 6 2 2 7
4
-1 -2 -3 -3
【输出样例】
1 2 3
1 3 2 2 4
3 2 1 1
【数据范围】
对全部的测试点,保证 1≤T≤5,1≤n≤10^5,−10^9≤ai≤10^9。
【算法分析】
● 离散化的本质,是映射。原理是将间隔很大的元素,映射到相邻的位置上,从而减少对空间的需求,也减少计算量。
cpp
#include <bits/stdc++.h>
using namespace std;
const int maxn=1e5+5;
int a[maxn];
int main() {
int n;
cin>>n;
for(int i=0; i<n; i++) {
cin>>a[i];
}
//discretization
sort(a,a+n);
int cnt=unique(a,a+n)-a;
//Output the discretized results
for(int i=0; i<cnt; i++) {
cout<<a[i]<<" -> "<<i+1<<endl;
}
return 0;
}
/*
in:
6
10 12 1000 -50 30 10
out:
-50 -> 1
10 -> 2
12 -> 3
30 -> 4
1000 -> 5
*/
● 离散化操作的作用
(1)减少数据范围(如将 [1e9, 2e9, 3e9] 映射为 [1,2,3]),节省存储空间。
(2)使数据适用于树状数组等需要紧凑下标的数据结构。
(3)保持原数据的偏序关系(若 a[i] < a[j],则离散化后仍有 a'[i] < a'[j])。
【算法代码一:下标从 0 开始】
● sort(t,t+n); 将数组 t 的第 0 到第 n-1 个元素升序排序,为去重和映射做准备。
● int cnt=unique(t,t+n)-t; 对排序后的数组去重,返回去重后的元素个数 cnt,此时 t[0..cnt-1] 为无重复的有序序列。
● a[i]=lower_bound(t,t+cnt,a[i])-t+1; 将原数组 a 的每个元素通过二分查找定位到 t 中的位置,减去基地址后得到离散化后的新值(范围是 1~cnt)。
cpp
#include <bits/stdc++.h>
using namespace std;
const int maxn=1e5+5;
int a[maxn],t[maxn];
int main() {
int T,n;
cin>>T;
while(T--) {
cin>>n;
for(int i=0; i<n; i++) {
cin>>a[i];
t[i]=a[i];
}
sort(t,t+n);
int cnt=unique(t,t+n)-t;
for(int i=0; i<n; i++) {
a[i]=lower_bound(t,t+cnt,a[i])-t+1;
cout<<a[i]<<" ";
}
cout<<endl;
}
return 0;
}
/*
in:
3
3
1 2 3
5
1 6 2 2 7
4
-1 -2 -3 -3
out:
1 2 3
1 3 2 2 4
3 2 1 1
*/
【算法代码二:下标从 1 开始】
cpp
#include <bits/stdc++.h>
using namespace std;
const int maxn=1e5+5;
int a[maxn],t[maxn];
int main() {
int T,n;
cin>>T;
while(T--) {
cin>>n;
for(int i=1; i<=n; i++) {
cin>>a[i];
t[i]=a[i];
}
sort(t+1,t+n+1);
int cnt=unique(t+1,t+n+1)-(t+1);
for(int i=1; i<=n; i++) {
a[i]=lower_bound(t+1,t+cnt+1,a[i])-t;
cout<<a[i]<<" ";
}
cout<<endl;
}
return 0;
}
/*
in:
3
3
1 2 3
5
1 6 2 2 7
4
-1 -2 -3 -3
out:
1 2 3
1 3 2 2 4
3 2 1 1
*/
【参考文献】
https://blog.csdn.net/hnjzsyjyj/article/details/153268411
https://blog.csdn.net/hnjzsyjyj/article/details/143275575