#求区间和(Java实现)题目:
假定有一个无限长的数轴,数轴上每个坐标上的数都是 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

##解题思维:
此题要运用离散化思维,将x,l,r各下标离散化,因为其本来的数轴是无限长的,不可能设置那么长的一个数组来存储所有数据,但n,m都是大于1小于10^ 5的,所以下标个数最多有3*10^5,可以用一个数组alls存储所有离散化后的坐标。
所以此题总共可以分为五个步骤:
1.输入数据n,m,确定操作和询问的次数
2.输入x,c并添加到数组add中;输入l,r并添加到数组query中;同时把x,l,r存入数组alls离散化
3.将alls数组进行排序(因为要进行二分查找,排序后才有单调性)和去重(alls数组存放的数是数轴上的下标)
4.利用find()函数二分查找离散化后的x对应的下标,并遍历add数组执行操作一
5.再查找离散化后的l,r对应的下标,再遍历query数组通过前缀和计算出l到r之间的数的和,执行查询二
###具体实现代码如下:

package lisanhua;

import java.util.*;

public class qujianhe {
    final static int N = 300010;
    static int n, m;
    static int[] a = new int[N];
    static int[] s = new int[N];
    static Scanner sc = new Scanner(System.in);
    public static void main(String[] args) {
        n = sc.nextInt();
        m = sc.nextInt();
        List<Integer> alls = new ArrayList<>();     //序列化数组,存x,l,r的下标并进行序列化
        List<pairs> add = new ArrayList<>();
        List<pairs> query = new ArrayList<>();

    //输入操作数x,c并将x,c打包存入add数组;将x存入离散化序列alls
        for(int i = 0; i < n; i ++){
            int x = sc.nextInt();
            int c = sc.nextInt();
            add.add(new pairs(x, c));
            alls.add(x);
        }

    //输入操作数l,r并将l,r打包存入query数组;并将l,r存入离散化序列alls
        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);
        }

    //排序和去重
        Collections.sort(alls);
        alls = removeDuplicate(alls);   //要去重是因为x和l,r可能一样(即是同一个点),x和x本身也可能会重复在一个点上加c
                                        //alls数组内存放的是数轴上的下标,所以alls数组内重复的数表示的都是同一个点

    //第一组操作
    for(pairs item:add){    //for each循环中item类型是和pairs一致的
        int index = find(item.first,alls);
        a[index] += item.second;
    }

    //a数组前缀和
        for(int i = 1; i <= alls.size(); i ++){
            s[i] = s[i - 1] + a[i];
        }

    //第二组操作
    for(pairs item:query){
        int l = find(item.first, alls);
        int r = find(item.second, alls);
        System.out.println(s[r] - s[l - 1]);
    }

    }

    //去重操作
    static List removeDuplicate(List<Integer> list) {
        List<Integer> temp = new ArrayList<>();
        temp.add(list.get(0));
        for(int i = 1; i < list.size(); i ++){
            if(!list.get(i).equals(list.get(i - 1)))    temp.add(list.get(i));
        }
        list.clear();
        list.addAll(temp);
        return list;
    }

    //查询离散化后的数组下标
    static int find(int x,List<Integer> list){
        int l = 0,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;   //考虑前缀和从1开始
    }

}

    //pairs类将x,c和l,r打包一起存储
class pairs{
    int first,second;
    public pairs(int first, int second){
        this.first = first;
        this.second = second;
    }
}