离散化(保证有序)
802. 区间和
假定有一个无限长的数轴,数轴上每个坐标上的数都是 \(0\)。
现在,我们首先进行 \(n\) 次操作,每次操作将某一位置 \(x\) 上的数加 \(c\)。
接下来,进行 \(m\) 次询问,每个询问包含两个整数 \(l\) 和 \(r\),你需要求出在区间 \([l,r]\) 之间的所有数的和。
输入格式
第一行包含两个整数 \(n\) 和 \(m\)。
接下来 \(n\) 行,每行包含两个整数 \(x\) 和 \(c\)。
再接下来 \(m\) 行,每行包含两个整数 \(l\) 和 \(r\)。
输出格式
共 \(m\) 行,每行输出一个询问中所求的区间内数字和。
数据范围
\(−10^9≤x≤10^9\),
\(1≤n,m≤10^5\),
\(−10^9≤l≤r≤10^9\),
\(−10000≤c≤10000\)
输入样例:
3 3
1 2
3 6
7 5
1 3
4 6
7 8
输出样例:
8
0
5
- 时间复杂度:\(O((n+m)\times logn)\)
代码
//离散化
#include<bits/stdc++.h>
#define fi first
#define se second
using namespace std;
vector<pair<int,int>> a,ask;
vector<int> alls,sum;
int n,m,l,r,x,c;
int main()
{
scanf("%d%d",&n,&m);
for(int i=0;i<n;i++)
{
scanf("%d%d",&x,&c);
a.push_back({x,c});
alls.push_back(x);
}
for(int i=0;i<m;i++)
{
scanf("%d%d",&l,&r);
ask.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());
int sz=alls.size();
sum.resize(sz,0);
for(int i=0;i<n;i++)
{
x=lower_bound(alls.begin(),alls.end(),a[i].fi)-alls.begin();
sum[x]+=a[i].se;
}
for(int i=1;i<sz;i++)sum[i]+=sum[i-1];
for(int i=0;i<m;i++)
{
auto [l,r]=ask[i];
l=lower_bound(alls.begin(),alls.end(),l)-alls.begin();
r=lower_bound(alls.begin(),alls.end(),r)-alls.begin();
printf("%d\n",sum[r]-(l-1<0?0:sum[l-1]));
}
return 0;
}