离散化模板题(离散化+区间和) 题解 详细注释

这算是一篇学习笔记。看了离散化的解说后,想写了一篇关于离散化+前缀和的模板题的题解(主要是代码的注释),来帮助自己加深印象,理解记忆。可能有表述的不是很清楚或者不是很恰当的的地方,请见谅

 

重点:离散化实质:映射+二分

 

题目:

假定有一个无限长的数轴,数轴上每个坐标上的数都是 00。

现在,我们首先进行 nn 次操作,每次操作将某一位置 xx 上的数加 cc。

接下来,进行 mm 次询问,每个询问包含两个整数 ll 和 rr,你需要求出在区间 [l,r][l,r] 之间的所有数的和。

输入格式

第一行包含两个整数 n 和 m。

接下来 n 行,每行包含两个整数 x 和 c。

接下来 m 行,每行包含两个整数 和 r。

输出格式

共 m 行,每行输出一个询问中所求的区间内数字和。

数据范围

109x109−109≤x≤109,
1n,m1051≤n,m≤105,
109lr109−109≤l≤r≤109,
10000c10000−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;
}

posted @ 2021-07-23 20:14  伶愔  阅读(202)  评论(0)    收藏  举报