Discretization
Principle and application:
When the value range of a given data is large, but the data is very scattered, the magnitude of useful data is far lower than the value range. For example, from − 1 0 9 -10^9 −109 ~ 1 0 9 10 ^ 9 109 random sampling 1 0 5 10^5 105 data, we can discretize this 1 0 5 10^5 105 data mapped to a size of 1 0 5 10^5 105. For example, data 2 100 3000 10000 200000 can be mapped into an array a[5].
Note:
1. Since there may be multiple operations, the mapping will be repeated, so it needs to be de duplicated first.
2. You need to build a function that can quickly find out the position of the value in the discretized array according to the value
Example introduction:
Title Description:
Suppose there is an infinite number axis, and the number on each coordinate on the number axis is 00.
Now, let's start with nn operations. Each operation adds cc to the number at a certain position xx.
Next, make mm queries. Each query contains two integers ll and rr. You need to find the sum of all numbers between the interval [l,r][l,r].
Input format
The first line contains two integers nn and mm.
Next nn lines, each containing two integers xx and cc.
Next mm lines, each containing two integers ll and rr.
Output format
There are mm lines in total, and each line outputs the sum of numbers in the interval required in the query.
Data range
− 1 0 9 ≤ x ≤ 1 0 9 − 1 0 9 ≤ x ≤ 1 0 9 , −10^9≤x≤10^9−10^9≤x≤10^9, −109≤x≤109−109≤x≤109,
1 ≤ n , m ≤ 1 0 5 , 1 ≤ n , m ≤ 1 0 5 , 1≤n,m≤10^5,1≤n,m≤10^5, 1≤n,m≤105,1≤n,m≤105,
− 1 0 9 ≤ l ≤ r ≤ 1 0 9 , − 1 0 9 ≤ l ≤ r ≤ 1 0 9 , −10^9≤l≤r≤10^9,−10^9≤l≤r≤10^9, −109≤l≤r≤109,−109≤l≤r≤109,
− 10000 ≤ c ≤ 10000 , − 10000 ≤ c ≤ 10000 −10000≤c≤10000,−10000≤c≤10000 −10000≤c≤10000,−10000≤c≤10000
Input example:
3 3 1 2 3 6 7 5 1 3 4 6 7 8
Output example:
8 0 5
Template & & solution:
#include <iostream> #include <vector> #include <algorithm> using namespace std; typedef pair<int, int> PII; // Rename pair const int N = 300010; // Add x locations and ask l + r locations, which adds up to 300000 int n, m; int a[N], s[N]; // a stores the discrete value, and s is its prefix and vector<int> alls; // Store the positions to be discretized, and use push_back() can ensure that data is stored from subscript 0 vector<PII> add, query; // Store locations where two operations are required int find(int x) // Given a value, then returns its footmark in the discrete array // Integer bisection is used { 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 r + 1; } vector<int>::iterator unique(vector<int> &a) // De duplication function source code { int j = 0; for (int i = 0; i < a.size(); i ++ ) if (!i || a[i] != a[i - 1]) a[j ++ ] = a[i]; // a[0] ~ a[j - 1] non repeated numbers in all a return a.begin() + j; // Since the prefix and array are used later, the subscript needs to be added with 1 } int main() { cin >> n >> m; for (int i = 0; i < n; i ++ ) { int x, c; cin >> x >> c; add.push_back({x, c}); // Save the pairs that need to be added alls.push_back(x); // Store useful locations from location 0 } for (int i = 0; i < m; i ++ ) { int l, r; cin >> l >> r; query.push_back({l, r}); // Save the pairs to be queried alls.push_back(l); // Store two endpoint locations alls.push_back(r); } // duplicate removal sort(alls.begin(), alls.end()); alls.erase(unique(alls), alls.end()); // Process insert for (auto item : add) { int x = find(item.first); a[x] += item.second; } // Preprocessing prefix and for (int i = 1; i <= alls.size(); i ++ ) s[i] = s[i - 1] + a[i]; // Handling inquiries for (auto item : query) { int l = find(item.first), r = find(item.second); cout << s[r] - s[l - 1] << endl; } return 0; }
Supplement (principle analysis of unique function):
1. unique function:
vector<int>::iterator unique(vector<int> &a) // De duplication function source code { int j = 0; for (int i = 0; i < a.size(); i ++ ) if (!i || a[i] != a[i - 1]) a[j ++ ] = a[i]; // a[0] ~ a[j - 1] non repeated numbers in all a return a.begin() + j; // Since the prefix and array are used later, the subscript needs to be added with 1 }
Take the following figure as an example:
[the external chain image transfer fails. The source station may have an anti-theft chain mechanism. It is recommended to save the image and upload it directly (img-fpkzrdi4-1632542807900) (C: \ users \ 33385 \ appdata \ roaming \ typora \ typora user images \ image-20210925115742. PNG)]
The number left after de preserving must satisfy the following properties
1. It's the first
2,a[i] != a[i - 1]
Therefore, we use the double pointer algorithm to traverse all numbers with the first pointer i, and the second pointer j represents the number of numbers currently saved to obtain the above function
2. Use unique for weight removal:
alls.erase(unique(alls), alls.end()); This sentence means that we delete all the numbers from the position of the return value of the unique (all) function to the end. In the figure, we delete the red part, that is, we complete the de duplication.