AcWing 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
显然,10^9的数据通过开数组是无法实现。所以,我们可以把区间的值存储在另一个数组中,也就是离散化。
#include<bits/stdc++.h>
using namespace std;
int num[200008],a[200080],v[200013],b[200011];
int n,m;
int main()
{
scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++)
{
scanf("%d%d",&a[i],&v[i]); //a为坐标
b[i]=a[i];
}
sort(b+1,b+n+1);
int cnt=unique(b+1,b+n+1)-b-1; //去重
for(int i=1;i<=n;i++)
{
a[i]=lower_bound(b+1,b+cnt+1,a[i])-b;
//从数组的1位置到cnt+1位置二分查找第一个大于或等于a[i]的数字
num[a[i]]+=v[i]; //赋值 (存在多次累加
}
for(int i=1;i<=cnt+1;i++)num[i]+=num[i-1]; //前缀和 ;优化时间
for(int i=1;i<=m;i++)
{
int x,y;
scanf("%d%d",&x,&y);
int l;l=lower_bound(b+1,b+cnt+1,x)-b; //查找
int r;r=lower_bound(b+1,b+cnt+1,y)-b;
if(b[r]>y)r--;
if(r<l)cout<<"0"<<endl;
else printf("%d \n",num[r]-num[l-1]);
}
return 0;
}