You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

81 lines
2.3 KiB

2 years ago
#include <bits/stdc++.h>
using namespace std;
typedef pair<int, int> PII;
const int N = 300010; // 上限n+2*m+10
int a[N]; // 映射后的数组
int s[N]; // a数组的前缀和数组
vector<int> alls; // 坐标集合
vector<PII> add; // 1、哪个位置2加上多少
vector<PII> query; // 1、开始点2:结束点
int n, m;
/**
* x
* ,
* @param x
* @return
*/
int find(int x) {
int l = 0, r = alls.size() - 1;
while (l < r) {
int mid = (l + r) >> 1;
if (alls[mid] >= x)
r = mid;
else
l = mid + 1;
}
return l;
}
// 883 ms
int main() {
// 输入数据
cin >> n >> m;
// 录入原始数据
while (n--) {
int x, c;
cin >> x >> c;
// 记录位置与值
add.push_back({x, c});
// 将位置记录到alls里
alls.push_back(x);
}
// 读入查询范围
int l, r;
while (m--) {
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());
// 生成a数组每次都在映射后的坐标位置将值变大c
for (int i = 0; i < add.size(); i++) {
PII item = add[i];
// find返回的是下标从0开始的位置这里为了使用前缀和要求a数据下标从1开始有1个偏移量
int x = find(item.first) + 1; // 映射为小范围的索引值
a[x] += item.second;
}
// 预处理前缀和
for (int i = 1; i < N; i++) s[i] = s[i - 1] + a[i];
// 处理询问(前缀和应用)
for (int i = 0; i < query.size(); i++) {
PII item = query[i];
// 根据原来的位置值,计算出映射后的位置值
l = find(item.first) + 1;
r = find(item.second) + 1;
// 利用一维前缀和计算区间和
cout << s[r] - s[l - 1] << endl;
}
return 0;
}