18.区间和

离散化,特指整数的离散化,保序的。

保序是指小的小,大的大。

值的范围比较大,但是个数比较少

值域很大,但是比较稀疏,我们用到的只是相对关系

排序去重后,这个数的下标就是这个数映射的值

 将它们映射到从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 }

 

posted @ 2020-06-30 16:34  kyk333  阅读(206)  评论(0)    收藏  举报