离散化:
含义
把分散不均匀的数值,进行映射处理,使得,数值分布均匀。
假设 值域为0 ~ 10 ^ 9 个数:10 ^ 5
a [] : 1 2 3 100 2000
1 2 3 4 5
- a中可能有重复元素 需要去重
- 如何算出 ai 离散后的值是多少 二分
//去重处理
vector<int>alls;
sort(alls.begin(),alls.end());
//unique函数:把数组里面重复的元素都放到后面,最后返回第一个重复元素的位置,
//erase函数:删除 a - b的数据
alls.erase(unique(alls.begin()),alls.end(),alls.end());
find函数里面,需要注意的是,我们是在查询x在去重后数组的位置。
假设 res 是去重数组,idx 是离散后的数组
res = 1 , 200 , 3000 ,100000
idx = 1 , 2, 3,4
对于离散,我们只是把数组和下标做一个映射。
//离散处理
int fd(int x){//找到第一个大于等于x的位置
int l = 1,r = n;
while (l < r){
int mid = l + r >> 1;
if (a[mid] >= x)r = mid;
else l = mid + 1;
}
return r + 1; //映射到 1 2 3....n
}
例题:802. 区间和
题意:
在一个无限长的数轴上,进行n次操作,在x坐标上加上c,进行m次查询操作,查询l到 r区间内的总和
思路:
离散化+前缀和。
#include <iostream>
#include <algorithm>
#include <vector>
#include <map>
using namespace std;
typedef long long ll;
typedef pair<int,int>PII;
const int N = 1e6+10;
int a[N];
int s[N];
vector<PII>add;
vector<PII>query;
vector<int>res;
int find(int x){
int l = 0, r = res.size() - 1;
while (l < r){
int mid = l + r >> 1;
if (res[mid] >= x)r = mid;
else l = mid + 1;
}
return r + 1;
}
int main(){
int n,m;
cin >> n >> m;
//存入坐标的添加值
for (int i = 1;i <= n; i++){
int x,c;
cin >> x >> c;
add.push_back({x,c});
res.push_back(x);
}
//存入查询的范围
for (int i = 1;i <= m;i++){
int l,r;
cin >> l >> r;
query.push_back({l,r});
res.push_back(l);
res.push_back(r);
}
//去重
sort(res.begin(),res.end());
res.erase(unique(res.begin(),res.end()),res.end());
//离散化之后 加上值
for (int i = 0 ;i < add.size();i++){
int x = find(add[i].first);
a[x] += add[i].second;
}
//前缀和处理
for (int i = 1;i <= res.size();i++){
s[i] = s[i-1] + a[i];
}
for (int i = 0;i < query.size();i++){
int l = find(query[i].first),r = find(query[i].second);
cout << s[r] - s[l-1] << endl;
}
return 0;
}