离散化模板题(离散化+区间和) 题解 详细注释
这算是一篇学习笔记。看了离散化的解说后,想写了一篇关于离散化+前缀和的模板题的题解(主要是代码的注释),来帮助自己加深印象,理解记忆。可能有表述的不是很清楚或者不是很恰当的的地方,请见谅。
重点:离散化实质:映射+二分
题目:
假定有一个无限长的数轴,数轴上每个坐标上的数都是 00。
现在,我们首先进行 nn 次操作,每次操作将某一位置 xx 上的数加 cc。
接下来,进行 mm 次询问,每个询问包含两个整数 ll 和 rr,你需要求出在区间 [l,r][l,r] 之间的所有数的和。
输入格式
第一行包含两个整数 n 和 m。
接下来 n 行,每行包含两个整数 x 和 c。
接下来 m 行,每行包含两个整数 l 和 r。
输出格式
共 m 行,每行输出一个询问中所求的区间内数字和。
数据范围
−109≤x≤109−109≤x≤109,
1≤n,m≤1051≤n,m≤105,
−109≤l≤r≤109−109≤l≤r≤109,
−10000≤c≤10000−10000≤c≤10000
输入样例:
3 3
1 2
3 6
7 5
1 3
4 6
7 8
输出样例:
8
0
5
代码:
#include<iostream>
#include<algorithm>
#include<algorithm>
using namespace std;
typedef pair<int, int> PII;
const int maxn=3e5+10; //点的范围是1e5,查询次数1e5,一次查询有两个坐标点,加起来一共3e5
int a[maxn];//储存离散化后对应的值
int s[maxn];//前缀和
vector<int> alls;//储存离散化前的数值
vector<PII> add;//保存插入的操作
vector<PII> query;//查询的区间范围
//二分查找第一个大于等于x的位置,该位置为x对应的离散化后的值
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;//前缀和从1开始,所以下标也要从1开始
}
int main() {
int n, m;
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);//x为c的位置,需要离散化
}
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(int i=0; i<add.size(); i++) {
int idx=find(add[i].first);
a[idx]+=add[i].second;//加上对应的c
}
//预处理前缀和
for(int i=1; i<=alls.size(); i++)
s[i]=s[i-1]+a[i];
//处理查询
for(int i=0; i<query.size(); i++) {
int l=find(query[i].first);
int r=find(query[i].second);//获得左右区间离散化后的值
cout<<s[r]-s[l-1]<<endl;
}
return 0;
}
浙公网安备 33010602011771号