AcWing 802. 区间和
题目概述
假定有一个无限长的数轴,数轴上每个坐标上的数都是 0 0 0。
现在,我们首先进行 n n n 次操作,每次操作将某一位置 x x x 上的数加 c c c。
接下来,进行 m m m 次询问,每个询问包含两个整数 l l l 和 r r r,你需要求出在区间 [ l , r l,r l,r] 之间的所有数的和。
输入格式
第一行包含两个整数 n n n 和 m m m。
接下来 n n n 行,每行包含两个整数 x x x 和 c c c。
再接下来 m m m 行,每行包含两个整数 l l l 和 r r r。
输出格式
共 m m m 行,每行输出一个询问中所求的区间内数字和。
数据范围
−
109
≤
x
≤
109
−109≤x≤109
−109≤x≤109,
1
≤
n
,
m
≤
105
1≤n,m≤105
1≤n,m≤105,
−
109
≤
l
≤
r
≤
109
−109≤l≤r≤109
−109≤l≤r≤109,
−
10000
≤
c
≤
10000
−10000≤c≤10000
−10000≤c≤10000
AC 代码
//其实我是菜狗代码只与y总代码差在一个地方QWQ
//2021年7月21日15:10:18 By ZenF1sh
#include <bits/stdc++.h>
using namespace std;
const int N = 3e5+10;
typedef long long LL;
typedef pair<LL,LL> PLL;
vector<LL> alls;
vector<PLL> add,query;
//找到数轴中坐标在数组中的下标
LL find(LL x) {
LL l = 0,r = alls.size() - 1;
while(l < r) {
LL mid = l+r >> 1;
if(alls[mid] >= x) r = mid;
else l = mid + 1;
}
return r+1;
}
int main() {
int n,m; cin >> n >> m;
LL a[N];
memset(a,0,sizeof(a));
for(int i = 0;i < n;i++) {
int x,c; cin >> x >> c;
add.push_back({x,c});
alls.push_back(x);
}
//存储数组下表位置进行离散化
for(int i = 0;i < m;i++) {
int l,r; cin >> l >> r;
query.push_back({l,r});
alls.push_back(l); alls.push_back(r);
}
//去重
sort(alls.begin(),alls.end());
alls.erase(unique(alls.begin(),alls.end()),alls.end());
//根据题目要求将对数轴上坐标加相应的数字
for(auto item : add) {
int x = find(item.first);
a[x] += item.second;
}
//由于a数组不会再用于是直接用它本身进行求前缀和
for(int i = 1;i <= alls.size();i++) {
a[i] = a[i-1] + a[i];
}
//前缀和求差得出区间和
for(auto item : query) {
int l = find(item.first)-1,r = find(item.second);
cout << a[r] - a[l] << endl;
}
return 0;
}
END