离散化
根据OI WIKI
离散化是一种数据处理的技巧,本质上可以看成是一种 哈希,其保证数据在哈希以后仍然保持原来的 全/偏序 关系。
通俗地讲就是当有些数据因为本身很大或者类型不支持,自身无法作为数组的下标来方便地处理,而影响最终结果的只有元素之间的相对大小关系时,我们可以将原来的数据按照排名来处理问题,即离散化。
用来离散化的可以是大整数、浮点数、字符串等等。
应用场景
- 题目给的数据范围非常大(开不了那么大的数组),但是数据又都是离散分布时,可以用离散化处理。
处理办法C++
// std::vector<int> arr;
std::vector<int> tmp(arr); // tmp 是 arr 的一个副本
std::sort(tmp.begin(), tmp.end());
tmp.erase(std::unique(tmp.begin(), tmp.end()), tmp.end());
for (int i = 0; i < n; ++i)
arr[i] = std::lower_bound(tmp.begin(), tmp.end(), arr[i]) - tmp.begin();
- 时间复杂度\(O(n * log n)\)
- 空间复杂度\(O(n)\)
例题
Leetcode LCP74
思路
题目逻辑很简单,就是用差分在数组上实现加减操作,难点是题目给的范围非常大,用数组表示大概率爆空间,其次是即使空间没有爆,差分完了做前缀和的时候遍历这个二维数组,时间也肯定会爆。
但是我们发现,一个矩形用在x轴上的两个端点和在y轴上的两个端点就可以表示,所以如果要创建数组,这个数组上的数据将是及其离散化的,所以可以使用离散化的技巧优化。
代码
class Solution {
public:
int fieldOfGreatestBlessing(vector<vector<int>>& forceField) {
vector<long long> xs, ys;
for (auto f : forceField){
long long i = f[0], j = f[1], side = f[2];
xs.push_back(2*i - side);
xs.push_back(2*i + side);
ys.push_back(2*j + side);
ys.push_back(2*j - side);
}
sort(xs.begin(), xs.end());
xs.erase(unique(xs.begin(), xs.end()), xs.end());
sort(ys.begin(), ys.end());
ys.erase(unique(ys.begin(), ys.end()), ys.end());
int n = xs.size(), m = ys.size(), diff[n+2][m+2];
memset(diff, 0, sizeof(diff));
for (auto f : forceField){
long long i = f[0], j = f[1], side = f[2];
int r1 = lower_bound(xs.begin(), xs.end(), 2*i-side) - xs.begin();
int r2 = lower_bound(xs.begin(), xs.end(), 2*i+side) - xs.begin();
int c1 = lower_bound(ys.begin(), ys.end(), 2*j-side) - ys.begin();
int c2 = lower_bound(ys.begin(), ys.end(), 2*j+side) - ys.begin();
++diff[r1+1][c1+1];
--diff[r1+1][c2+2];
--diff[r2+2][c1+1];
++diff[r2+2][c2+2];
}
int ans = 0;
for (int i = 1; i <= n; i++){
for (int j = 1; j <= m; j++){
diff[i][j] += diff[i-1][j] + diff[i][j-1] - diff[i-1][j-1];
ans = max(ans, diff[i][j]);
}
}
return ans;
}
};
标签:tmp,begin,end,离散,xs,ys,side
From: https://www.cnblogs.com/califeee/p/18643809