802. 区间和

110 阅读1分钟

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

输入样例:

3 3

1 2

3 6

7 5

1 3

4 6

7 8

输出样例:

8

0

5

代码

知识点:离散化

# 查询l,r很大会MLE,但是稀疏,可以离散化处理
N = 300010 # 3 * 10^5 ,x,l,r最大分别为10^5
n,m = map(int,input().split())
query = []
idxarr = [] # 存放真正用到的下标
add = []
for _ in range(n):
    x , c = map(int,input().split())
    add.append((x,c))
    idxarr.append(x)

for _ in range(m):
    l,r = map(int,input().split())
    query.append((l,r))
    idxarr.append(l)
    idxarr.append(r)

idxarr = sorted(list(set(idxarr))) # 原数组,包含所有的查询和加c的下标,去重排序,便于二分查找

from bisect import bisect_left
def find(i):
    return bisect_left(idxarr,i) + 1  # 下标是1开始

maparr = [0 for _ in range(N)] # 映射数组


for x,c in add:
    maparr[find(x)] += c


presum = [0 for _ in range(N)] #前缀和
for i in range(1,len(idxarr) + 2):
    presum[i] = presum[i-1] + maparr[i]


for l,r in query:
    print(presum[find(r)] - presum[find(l)-1])