离散化
什么是离散化:假设有1000个数,每个数的数值范围是0-10^1000,如果我们去用数组下表处理这些数,一般情况下当每个数的取值范围较小,我们可以用数组下标来存储,但是这样就要开很大的空间,所以我们需要将大数映射成小数,这样就只需要开1000个数的空间。
比如将4999 50326 323232 映射成 2 3 4,离散化是一种优化方法。
下面我们用一道题来学习离散化。
const int N = 1000010;
typedef pair<int, int> PII;
int n, m;
int a[N],s[N];
vector<int> alls;//所有要离散化的数,包括l,r
vector<PII> add, query;//add 存储数组某一位置加上的数c ,query 存储每次询问的区间l,r
//查找离散化后的数的下标
int find(int x) {
int l = 0, r = alls.size() - 1;
while (l < r) {
int mid = (l + r)/2;
if (alls[mid] >= x) r = mid;
else l = mid + 1;
}
return r + 1;//从1开始映射
}
int main(){
cin>>n>>m;
for(int i=0;i<n;i++){
int x, c;
cin>> x >> c;
add.push_back({x,c});//添加数组位置上要增加的数
alls.push_back(x);//添加要离散化的数
}
for(int i=0;i < m; i++){
int l ,r ;
cin>> l >>r;
query.push_back({l,r});//添加要询问的区间
alls.push_back(l);
alls.push_back(r);//添加要离散化的区间数
}
//去重,因为可能会有相同的数
sort(alls.begin(),alls,end());
alls.erase(unique(alls.begin(),alls.end()),alls.end());
//离散化并将数组位置为x的数增加C
for(auto item: add){
int x = find(item.first);
a[x]+=item.second;
}
//处理前缀和
for(int i;i<=alls.size() ;i++) s[i] = s[i-1]+a[i];
//处理询问
for(auto item:query){
int l = find(item.first) ,r = find(item.second);
cout<< s[r]-s[l-1]<<endl;
}
return 0;
}