原理
离散化是把无限空间中有限的个体映射到有限的连续区间 ,核心作用:去重 + 压缩坐标
当题目中数据范围很大,但是数据的总量不是很大,**并且我们需要用数据的值来映射数组的下标时,**我们就可以用离散化的思想先预处理一下所有的数据,使的每一个数据都映射成一个范围较小的值。
比如: [9, 99, 9999, 9999999] 离散之后就变成 [1, 2, 3, 4]。
细节:离散化后只是让对应位置的元素有了新的下标
离散化模板
1.静态数组实现
cpp
#include <bits/stdc++.h>
using namespace std;
#define int long long
#define endl '\n'
const int N = 2e5 + 10;
int n;
int a[N];
int t[N];
int pos; // 离散化后的大小
int find(int x)
{
return lower_bound(t + 1, t + 1 + pos, x) - t; // 让下标从1开始
}
void solve()
{
cin >> n;
for(int i = 1; i <= n; i++)
{
cin >> a[i];
t[i] = a[i];
}
// 排序 + 去重
sort(t + 1, t + 1 + n); // 排序
pos = unique(t + 1, t + 1 + n) - t - 1; // 去重
for(int i = 1; i <= n; i++)
{
cout << find(a[i]) << endl; // 离散化后的结果
}
}
signed main()
{
ios::sync_with_stdio(false);
cin.tie(nullptr);
int _ = 1;
cin >> _;
while(_--)
{
solve();
}
return 0;
}
不建议用unordered_map来离散化,有时候效率低,有被卡TLE
2.动态数组实现
cpp
#include <bits/stdc++.h>
using namespace std;
#define int long long
#define endl '\n'
void solve()
{
int n; cin >> n;
vector<int> a(n + 1);
for(int i = 1; i <= n; i++)
{
cin >> a[i];
}
vector<int> t = a;
sort(t.begin(), t.end()); // 排序
t.erase(unique(t.begin(), t.end()), t.end()); // 去重
int pos = t.size();
for(int i = 1; i <= n; i++)
{
cout << lower_bound(t.begin(), t.end(), a[i]) - t.begin() + 1 << endl;
}
}
signed main()
{
ios::sync_with_stdio(false);
cin.tie(nullptr);
int _ = 1;
cin >> _;
while(_--)
{
solve();
}
return 0;
}