离散化
区间和
题目
假定有一个无限长的数轴,数轴上每个坐标上的数都是 0。
现在,我们首先进行 n 次操作,每次操作将某一位置 x 上的数加 c。
接下来,进行 m 次询问,每个询问包含两个整数 l 和 r,你需要求出在区间 [l,r] 之间的所有数的和。
图解
代码
#include<iostream>
#include<vector>
#include<algorithm>
using namespace std;
const int N = 300010;//n+m的上限
vector<int>alls; //添加 查询 所有用到的点
vector<pair<int,int>>add,query; //添加 和 查询
int a[N]; //记录数轴中添加的数
int s[N]; //a[]的前缀和
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;//返回r + 1,是因为a[],s[]都是从下标1开始的
}
int main()
{
int n,m;
cin>>n>>m;
for(int i = 0;i < n;i++)//添加操作
{
int x,c;
scanf("%d %d",&x,&c);
add.push_back({x,c});
alls.push_back(x);
}
for(int i = 0;i < m;i++)//查询操作
{
int l,r;
scanf("%d %d",&l,&r);
query.push_back({l,r});
alls.push_back(l);
alls.push_back(r);
}
//对alls去重
sort(alls.begin(),alls.end());
erase(unique(alls.begin(),alls.end()),alls.end());
//n次添加操作
for(auto t:add)
{
int x = find(t.first);
a[x] += t.second;
}
//前缀和操作
for(int i = 1;i <= alls.size();i++)s[i] = s[i - 1] + a[i];
//m次查询操作
for(auto t:query)
{
int l = find(t.first);
int r = find(t.second);
printf("%d\n",s[r] - s[l - 1]);
}
return 0;
}