离散化
常 用 于 数 据 范 围 较 大 , 但 是 数 据 比 较 分 散 的 情 况 。 常用于数据范围较大,但是数据比较分散的情况。 常用于数据范围较大,但是数据比较分散的情况。
例题:
假定有一个无限长的数轴,数轴上每个坐标上的数都是0。
现在,我们首先进行 n 次操作,每次操作将某一位置x上的数加c。
接下来,进行 m 次询问,每个询问包含两个整数l和r,你需要求出在区间[l, r]之间的所有数的和。
输入格式
第一行包含两个整数n和m。
接下来 n 行,每行包含两个整数x和c。
再接下里 m 行,每行包含两个整数l和r。
输出格式
共m行,每行输出一个询问中所求的区间内数字和。
数据范围
−109≤x≤109,
1≤n,m≤105,
−109≤l≤r≤109,
−10000≤c≤10000
输入样例:
3 3
1 2
3 6
7 5
1 3
4 6
7 8
输出样例:
8
0
5
具体落实:
①
、
三
个
数
组
,
分
别
处
理
:
离
散
化
、
修
改
(
增
加
)
、
查
询
(
求
和
)
操
作
。
第
一
个
数
组
a
l
l
s
,
依
次
存
储
所
有
读
入
的
下
标
,
需
要
查
找
时
通
过
二
分
输
出
数
组
中
离
散
化
后
的
下
标
。
第
二
个
和
第
三
个
数
组
分
别
记
录
各
自
的
操
作
,
用
p
a
i
r
存
储
到
数
组
中
去
。
②
、
先
将
a
l
l
s
数
组
排
序
(
方
便
修
改
和
查
询
的
时
候
用
二
分
)
,
再
把
重
复
下
标
去
除
。
③
、
按
照
输
入
的
顺
序
遍
历
操
作
数
组
,
利
用
f
i
n
d
查
找
到
离
散
化
后
的
下
标
,
依
次
进
行
操
作
。
①、三个数组,分别处理:离散化、修改(增加)、查询(求和)操作。\\\qquad第一个数组alls,依次存储所有读入的下标,需要查找时通过二分输出数组中离散化后的下标。\\\qquad第二个和第三个数组分别记录各自的操作,用pair存储到数组中去。\\②、先将alls数组排序(方便修改和查询的时候用二分),再把重复下标去除。\\③、按照输入的顺序遍历操作数组,利用find查找到离散化后的下标,依次进行操作。
①、三个数组,分别处理:离散化、修改(增加)、查询(求和)操作。第一个数组alls,依次存储所有读入的下标,需要查找时通过二分输出数组中离散化后的下标。第二个和第三个数组分别记录各自的操作,用pair存储到数组中去。②、先将alls数组排序(方便修改和查询的时候用二分),再把重复下标去除。③、按照输入的顺序遍历操作数组,利用find查找到离散化后的下标,依次进行操作。
模板:
#include <iostream>
#include <algorithm>
#include <vector>
#define P pair<int,int>
#define x first
#define y second
using namespace std;
const int N=3e5+10;
int n,m,a[N],s[N];
vector<int> alls;
vector<P> 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; //要处理前缀和,所以下标从1开始
}
int main()
{
cin>>n>>m;
for(int i=0;i<n;i++)
{
int x,c;
cin>>x>>c;
alls.push_back(x);
add.push_back({x,c});
}
for(int i=0;i<m;i++)
{
int l,r;
cin>>l>>r;
alls.push_back(l);
alls.push_back(r);
query.push_back({l,r});
}
sort(alls.begin(),alls.end());
alls.erase(unique(alls.begin(),alls.end()),alls.end());
for(int i=0;i<n;i++)
{
int p=find(add[i].x);
a[p]+=add[i].y;
}
for(int i=1;i<=alls.size();i++) s[i]=s[i-1]+a[i];
for(int i=0;i<m;i++)
{
int l=find(query[i].x),r=find(query[i].y);
cout<<s[r]-s[l-1]<<endl;
}
return 0;
}