离散化,特指整数的离散化,保序的。
保序是指小的小,大的大。
值的范围比较大,但是个数比较少
值域很大,但是比较稀疏,我们用到的只是相对关系
排序去重后,这个数的下标就是这个数映射的值
将它们映射到从0开始的自然数
unique函数返回去重后数组的尾端点
然后把返回值和结尾中间的所有部分删掉
return r + 1是映射到1,2,...
return r是映射到0, 1, 2, ...
本题因为要求前缀和,所以从1开始映射
我们最多只会用到3 * 10 ^ 5个
手写unique函数
1 #include <bits/stdc++.h> 2 using namespace std; 3 typedef pair<int, int> PII; 4 const int N = 300010; 5 int a[N], s[N]; 6 //a数组存的数 7 //s数组是前缀和 8 vector<int> alls; //所有需要离散化的值 9 vector<PII> add, query; //插入操作,询问操作 10 int find(int x) { 11 int l = 0, r = alls.size() - 1; 12 while (l < r) { 13 int mid = (l + r) / 2; 14 if (alls[mid] >= x) { 15 r = mid; 16 } else { 17 l = mid + 1; 18 } 19 } 20 return l + 1; 21 } 22 int main() { 23 int n, m; 24 cin >> n >> m; 25 for (int i = 0; i < n; i++) { 26 int x, c; 27 cin >> x >> c; 28 add.push_back({x, c}); 29 alls.push_back(x); //将x加入待离散化的数组中 30 } 31 for (int i = 0; i < m; i++) { 32 int l, r; 33 cin >> l >> r; 34 query.push_back({l, r}); 35 alls.push_back(l); 36 alls.push_back(r); 37 } 38 sort(alls.begin(), alls.end()); //先排序 39 alls.erase(unique(alls.begin(), alls.end()), alls.end()); //去重 40 for (int i = 0; i < add.size(); i++) { //在某一点加上一个数 41 int x = find(add[i].first); 42 a[x] += add[i].second; 43 } 44 for (int i = 1; i <= alls.size(); i++) { //求前缀和 45 s[i] = s[i - 1] + a[i]; 46 } 47 for (int i = 0; i < query.size(); i++) { //处理询问 48 int l = find(query[i].first), r = find(query[i].second); 49 cout << s[r] - s[l - 1] << endl; 50 } 51 return 0; 52 }