假定有一个无限长的数轴,数轴上每个坐标上的数都是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
#include <stdio.h>
void quicksort(int a[],int b[],int lo,int hi);
int findleftk(int a[],int lo,int hi,int k); //二分查找 重复元素最左侧的一个
int findrightk(int a[],int lo,int hi,int k);
int main(){
int n,m,i,j,k,p,q;
scanf("%d %d",&n,&m);
int a[n],b[n],sum[n]; //a[]存下标 b[]存数值
for(i=0;i<n;i++) scanf("%d %d",&a[i],&b[i]);
quicksort(a,b,0,n);
sum[0]=b[0];
for(i=1;i<n;i++) sum[i]=sum[i-1]+b[i];
for(i=0;i<m;i++){
scanf("%d %d",&p,&q);
j=findleftk(a,0,n,p); //先二分查找
k=findrightk(a,0,n,q);
if(j<=k) printf("%d\n",sum[k]-sum[j]+b[j]);
else printf("0\n");
//暴力求和会超时 用前缀和来求
// sum=0;
// for(j=0;j<n;j++){
// if(a[j]>=p && a[j]<=q) sum+=b[j];
// }
// printf("%d\n",sum);
}
return 0;
}
int findleftk(int a[],int lo,int hi,int k){
if(hi-lo<=2){
if(a[lo]>=k) return lo;
else if(a[lo+1]>=k) return lo+1;
else return lo+2;
}
else{
int mid=(lo+hi)/2;
if(a[mid]<k) return findleftk(a,mid+1,hi,k);
else return findleftk(a,lo,mid+1,k);
}
}
int findrightk(int a[],int lo,int hi,int k){
if(hi-lo<=2){
if(a[lo+1]<=k) return lo+1;
else if(a[lo]<=k) return lo;
else return lo-1;
}
else{
int mid=(lo+hi)/2;
if(a[mid]>k) return findrightk(a,lo,mid,k);
else return findrightk(a,mid,hi,k);
}
}
void quicksort(int a[],int b[],int lo,int hi){
int n=hi-lo,i=lo,j=hi-1;
if(n<=1) return;
else{
int t=a[lo],p=b[lo];
while(i<j){
while(i<j && a[j]>t) j--;
if(i<j){
a[i]=a[j];
b[i++]=b[j];
}
while(i<j && a[i]<t) i++;
if(i<j){
a[j]=a[i];
b[j--]=b[i];
}
}
a[i]=t;
b[i]=p;
quicksort(a,b,lo,i);
quicksort(a,b,i+1,hi);
}
}