题解 B3694 数列离散化
link
简而言之,离散化就是把一个数列转化为由小到大的排名来缩小范围。
离散化需要这个题不用数字本身。
举个例子:
-2002 448799 1 49932 35793
离散化后就是:
1 5 2 4 3
实现
考虑如何实现。
首先由于离散化前后数的顺序不能发生变化,我们需要复制一份:
for (int i = 1; i <= n; ++i) c[i] = a[i];
然后需要排序来确定顺序:
sort (a + 1, a + n + 1);
最后在
for (int i = 1; i <= n; ++i) {
rank[i] = lower_bound(c + 1, c + n + 1) - c;
}
注意这里为什么不减 (c + 1)
:题目说 :
定义
表示数列 中比 小的不同数字个数再加一。
所以减去的应少
而且由于
lower_bound( begin,end,num)
:从数组的begin
位置到end - 1
位置二分查找第一个大于等于num
的数字,找到返回该数字的地址,不存在则返回end
。
则如果某个数不止 lower_bound
返回的是最后一个的地址,然而我们想要的是第一个。
于是我们就需要去重。
unique 即可。
int cnt = unique(c + 1, c + n + 1) - (c + 1);
于是在 lower_bound
时就需要lower_bound(c + 1, c + cnt + 1)
而不是 lower_bound(c + 1, c + n + 1)
Code
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N = 1e5 + 10;
int n;
int a[N];
int c[N];
void solve() {
cin >> n;
for (int i = 1; i <= n; ++i) {
cin >> a[i];
c[i] = a[i];
}
sort (c + 1, c + n + 1);
int cnt = unique(c + 1, c + n + 1) - (c + 1);
for (int i = 1; i <= n; ++i) {
a[i] = lower_bound(c + 1, c + cnt + 1, a[i]) - c;
}
for (int i = 1; i <= n; ++i) cout << a[i] << " "; //不是 c[i]!!!
cout << '\n';
}
int main() {
ios::sync_with_stdio(false); cin.tie(0), cout.tie(0);
int T; cin >> T; while (T --) solve();
return 0;
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 地球OL攻略 —— 某应届生求职总结
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 提示词工程——AI应用必不可少的技术
· .NET周刊【3月第1期 2025-03-02】