所谓离散化是指,原本一个很大的数据范围,映射后在一个很小的区间
802. 区间和
思路
1.首先将所有数的下标存在一个数组 alls 中
2.把需要查询区间范围也存入 alls ,然后去重排序
3.根据插入的数据,把该值映射进一个数组
4.利用前缀和,求区间的范围
简言之,就是把所有需要用到的数组下标存起来,把下标和值映射进一个数组。相比于传统写法就节省了很多空间
源码
#include<bits/stdc++.h>
using namespace std;
typedef pair<int,int> PII;
const int N=1000010;
int n,m;
int a[N],s[N];
vector<int>alls;
vector<PII>add,query;
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 r+1;
}
int main(){
cin>>n>>m;
for(int i=0;i<n;i++){
int x,c;
cin>>x>>c;
add.push_back({x,c});//存入需要插入的数,用于接下的 add操作
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());
//增加每个数
for(vector<PII>::iterator item=add.begin();item!=add.end();item++){
int x=find(item->first);
a[x]+=item->second;
}
//预处理求前缀和
for(int i=1;i<=alls.size();i++) s[i]=s[i-1]+a[i];
//求每个区间的和
for(vector<PII>::iterator item=query.begin();item!=query.end();item++){
int l=find(item->first),r=find(item->second);
cout<<s[r]-s[l-1]<<endl; //输出区间和
}
return 0;
}