简单说一下个人理解:
数值范围太大了所以不能直接求前缀和,先排序 , 用下标来代表每一个值,下标最多到n,所以方案可选,
操作次数保存,按每个值去找对应下标,然后用一个新的数组来存储操作后的值,下标更大的值对应的就一定更大
import java.util.*;
public class Main{
public static void main(String[] args){
Scanner sc=new Scanner(System.in);
int n=sc.nextInt();
int m=sc.nextInt();
int N=300010;
int a[]=new int[N];//离散后的数组
int s[]=new int[N];//a的前缀和
List<Integer> alls=new ArrayList<>();
List<pairs> add=new ArrayList<>();//n个操作 x位置+c
List<pairs> query=new ArrayList<>();//m个询问 l~~r的和
for(int i=0;i<n;i++){
int x=sc.nextInt();
int c=sc.nextInt();
add.add(new pairs(x,c));
alls.add(x);
}
for(int i=0;i<m;i++){
int l=sc.nextInt();
int r=sc.nextInt();
query.add(new pairs(l,r));
alls.add(l);
alls.add(r);
}
//1 排序 2 去重(可有可无),重复没有意义但是也不影响结果
Collections.sort(alls);
int unique=unique(alls);
alls=alls.subList(0,unique);
//n个操作且把操作后的数据映射到a数组里面;
for(pairs item:add){
int index=fine(item.first,alls);
a[index]+=item.second;
}
//前缀和
for(int i=1;i<=alls.size();i++) s[i]=s[i-1]+a[i];
//求区间和
for(pairs item:query){
int l=fine(item.first,alls);
int r=fine(item.second,alls);
System.out.println(s[r]-s[l-1]);
}
}
//在list链表里查找x的位置 以数组下标1开头
static int fine(int x,List<Integer> list){
int l=0;
int r=list.size()-1;
while(l<r){
int mid=l+r>>1;
if(list.get(mid)>=x)
r=mid;
else
l=mid+1;
}
return l+1;
}
//去重
public static int unique(List<Integer> list){
int j=0;
for(int i=0;i<list.size();i++){
if(i==0||list.get(i)!=list.get(i-1)){
list.set(j,list.get(i));
j++;
}
}
return j;
}
}
//两个数的引用数据类型
class pairs{
int first,second;
public pairs(int first,int second){
this.first=first;
this.second=second;
}
}