整数-保序-离散化
将所有的待离散化的值,按顺序映射
特点:
1. 待需要操作的数和其下标对应,但是下标范围太大,数组无法存储
2. 整数
3. 映射完成后顺序是不变的
过程:
1. 确定需要离散化的数量级,即最多有多少个点能被离散化
2. 先将所有需要离散化的点用vector收集,将这些点排序,并用unique去重。此时所有的点,就已经映射成其下标了
3. 对于每个离散化的点x,通过二分法找大于等于x的第一个离散化的点的下标l
#include <iostream>
#include <cstdio>
#include <cstring>
#include <vector>
#include <algorithm>
using namespace std;
const int N = 300010;
vector<int> alls; //用来存所有下标,也就是所有需要离散化的点
int a[N], s[N]; // a是映射后的数组,通过下标和alls中的值绑定
typedef pair<int, int> PII;
vector<PII> add, query;
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 + 1;
}
int main() {
int n, m;
cin >> n >> m;
for (int i = 0; i < n; i++) {
int x, c;
scanf("%d%d", &x, &c);
add.push_back({x, c});
alls.push_back(x);
}
for (int i = 0; i < m; i++) {
int l, r;
scanf("%d%d", &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 (int i = 0; i < add.size(); i++) {
int x = find(add[i].first);
a[x] += add[i].second;
}
for (int i = 1; i <= N; i++) { //求前缀和
s[i] = s[i - 1] + a[i];
}
for (int i = 0; i < query.size(); i++) {
int l = find(query[i].first), r = find(query[i].second);
printf("%d\n", s[r] - s[l - 1]);
}
return 0;
}