题目来源:AcWing 802

假定有一个无限长的数轴,数轴上每个坐标上的数都是 00。

现在,我们首先进行 nn 次操作,每次操作将某一位置 xx 上的数加 cc。

接下来,进行 mm 次询问,每个询问包含两个整数 ll 和 rr,你需要求出在区间 [l,r][l,r] 之间的所有数的和。

  

  这道题乍一看仿佛能直接用前缀和做出来,但是由于他坐标的大小到达了10^9会爆内存空间,所以我们必须要开一个vector数组 alls来存储需要等待离散化的下标,我们是通过二分的方法来实现查询离散化后的下标是多少的

  而且我们需要注意就是就是alls必须进行排序和去重,排序是因为我们需要用到二分,但是由于在插入坐标时可能会重复的插入一个数,会导致同一个数会离散化出来不同的结果,下面我贴出去重的代码块

alls.erase(unique(alls.begin(), alls.end()), alls.end());

alls中存储的是坐标而不是我们要进行加减的值C,此时alls的下标就是坐标离散化之后的值。此时我们假定每一组数的坐标为z存放于vector数组 add中。

    for(auto item : add)
    {
        int x = find(item.first);//坐标离散化之后的值
        a[x] += item.second;
    }

此时我们已经完成了离散化和值的累加,现在我们只需要求前缀和即可

    for (int i = 1; i <= alls.size(); i ++ ) s[i] = s[i - 1] + a[i];

接下来有m对查询,我们都把他们的左右坐标存储在vector数组 query中, 同理我们也会对l和r进行离散化,然后我们在运用前缀和的知识便求到了不同区间的和

    for (auto item : query)
    {
        int l = find(item.first), r = find(item.second);
        cout << s[r] - s[l - 1] << endl;
    }