离散化(整数)
(整数有序)离散化就是将少量较大范围的数值,映射到从0开始的连续的自然数。
注意:
①数值中可能含有重复元素,故需要去重;
②如何计算出num离散化后的数值 => 二分。
【题目描述】
假定有一个无限长的数轴,数轴上每个坐标上的数都是 0。
现在,我们首先进行 n 次操作,每次操作将某一位置 x 上的数加 c。
接下来,进行 m 次询问,每个询问包含两个整数 l 和 r,你需要求出在区间 [l,r] 之间的所有数的和。
【输入格式】
第一行包含两个整数 n 和 m。
接下来 n 行,每行包含两个整数 x 和 c。
再接下来 m 行,每行包含两个整数 l 和 r。
【输出格式】
共 m 行,每行输出一个询问中所求的区间内数字和。
【数据范围】
−109≤x≤109,
1≤n,m≤105,
−109≤l≤r≤109,
−10000≤c≤10000
【输入样例】
3 3
1 2
3 6
7 5
1 3
4 6
7 8
【输出样例】
8
0
5
鉴于数据x的范围十分大,而插入操作次数n以及问询操作次数m相较于x比较小,即插入数据范围较大,但数量比较少,如果直接开大数组计算前缀和比较浪费时间空间,因此使用离散化思想,将所有用到的坐标离散化到自然数1开始的所有自然数中,映射到1开始主要是为了方便计算前缀和。
至于如何查找x映射后的自然数,使用二分查找即可。
1 #include <iostream> 2 #include <vector> 3 #include <algorithm> 4 using namespace std; 5 const int N = 300009; 6 int s[N]; 7 vector<int> alls; 8 vector <pair<int,int>> add,query; 9 int n,m; 10 11 int find(int x) 12 { 13 int l = 0,r = alls.size() - 1; 14 while(l < r) 15 { 16 int mid = l + r >> 1; 17 if(alls[mid] >= x) 18 r = mid; 19 else 20 l = mid + 1; 21 } 22 return r + 1; 23 } 24 25 int main() 26 { 27 cin >> n >> m; 28 for(int i = 0;i < n;++i) 29 { 30 int x,c; 31 cin >> x >> c; 32 add.push_back({x,c}); 33 alls.push_back(x); 34 } 35 for(int i = 0;i < m;++i) 36 { 37 int l,r; 38 cin >> l >> r; 39 query.push_back({l,r}); 40 alls.push_back(l); 41 alls.push_back(r); 42 } 43 sort(alls.begin(),alls.end()); 44 alls.erase(unique(alls.begin(),alls.end()),alls.end()); 45 for(int i = 0;i < add.size();++i) 46 s[find(add[i].first)] += add[i].second; 47 for(int i = 1;i <= alls.size();++i) 48 s[i] += s[i - 1]; 49 for(auto& q:query) 50 cout << s[find(q.second)] - s[find(q.first) - 1] << endl; 51 return 0; 52 }

浙公网安备 33010602011771号