1.自然语言描述
离散化是一种对无限集合内有限对象的处理方法;当问题的值域是一个无限集合,有用的对象之间相隔很远,遍历集合中的每个对象是天方夜谭,所以必须要通过一些方法把无限空间中有用的对象(符合条件的对象)映射到一个有限集合中,以便于后续操作。关于离散化更专业的解释请点这儿:百度百科对于离散化的解释
离散化有三个主要步骤:
排序:将无限集合中有限对象集中并排序。
去重:去除集中后重复出现的对象。
二分查找:对于每个要进行处理的对象,找出在序列中的位置。
2.代码描述
题目:Acwing.802 区间和题目链接
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <vector>
using namespace std;
const int MAXN=3e5+10;
typedef pair<int,int> PII;
vector<PII> add,query;
vector<int> alls;//记录所有实际涉及到的点(对象),以此初步实现将无限空间压缩为有限空间
int a[MAXN],s[MAXN];
int n,m,x,c,l,r;
int find(int x)
{
int l=0,r=alls.size()-1;//二分查找:寻找每一个涉及操作的点在有限空间内的升序位置.
while(l<r){
int mid=l+r>>1;
if(alls[mid]>=x)
r=mid;
else
l=mid+1;
}
return l;
}
int main(void)
{
cin>>n>>m;
for(int i=0;i<n;i++){
cin>>x>>c;
add.push_back({x,c});
alls.push_back(x);
}
for(int i=0;i<m;i++){
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());//去重
for(auto it:add){
int x=find(it.first);
a[x]+=it.second;
}
for(int i=0;i<alls.size();i++)
s[i]=s[i-1]+a[i];
for(auto it:query){
int l=find(it.first),r=find(it.second);
cout<<s[r]-s[l-1]<<endl;
}
return 0;
}
//离散化:将无限空间的有限点(对象)映射到有限空间中去.形象一点就是,将无限空间中稀疏的一系列点进行有限稠密化处理.