subject
Title screenshot:
![image-20211201234641418](C:\Users\long yongcheng\AppData\Roaming\Typora\typora-user-images\image-20211201234641418.png)
thinking
60 point answer
My first idea is to open a two-dimensional array, which is equivalent to opening a two-dimensional table with two rows and many columns (why do you say many columns? Because it mainly depends on how large you have), then the array subscript represents the matrix subscript, and then multiply and add the values of their corresponding subscripts to achieve the content required by the topic.
code
/* Sparse vector */ #include <bits/stdc++.h> #include <iostream> using namespace std; const int N = 1e8 + 10; int arr[2][N]; int n, a, b; int main() { int index, value; cin >> n >> a >> b; for (int i = 0; i < a; i++) { cin >> index >> value; arr[0][index]= value; } for (int i = 0; i < b; i++) { cin >> index >> value; arr[1][index] = value; } int res = 0; for (int i = 0; i < n; i++) { res =arr[0][i] * arr[1][i]+res; } cout << res; return 0; } /* 10 3 4 4 5 7 -3 10 1 1 10 4 20 5 30 7 40 */
However, this solution can only get 60 points. Why? Look at the requirements of the problem. The data range of n is 1e9, but we can't see such a large array. Therefore, we can't pass the last four test samples of the problem. Therefore, we must think of a new solution.
Double pointer algorithm
crap
Coincidentally, not long ago, I just saw acwingyxc's basic algorithm class and saw his double pointer algorithm. At that time, I wanted to write some notes, but I found that it was not easy to write, so I had to stop. When I was doing this problem, I also wanted to think of the double pointer algorithm, but what I wrote was still wrong. As for why, I will talk about it later, Also, when I was writing the topic, I thought of using discretization, but I didn't write it myself. Forget it, stop talking nonsense. Let's start:
text
We can think like this: for these two vectors u and v, we can use a structure to store the index of their useful value and its value , then find the points with equal subscripts in the two vectors, multiply and add their values to get the inner product of the two vectors. The idea is like this, and it should not be difficult to understand. Then let's talk about the advantages of the double pointer algorithm. After that, you should also know about the double pointer.
Traditional processing
According to our consistent thinking, if we want to find the value with equal subscripts in two vectors, we can temporarily determine a value of one vector, that is, as the first cycle, and then traverse the other vector to find the subscript corresponding to the value, which is the second cycle. Then let's analyze the time complexity:
The maximum dimension of two vectors can reach 5e5, so the time complexity is \ (O(n^2)=(5e5)^2=25*e^{10} \) , we probably know that the data that the computer can process in 1s is 1e8, and the time required for our problem is 2 seconds. That is to say, if we process the data in this way, the time spent is far more than 2 seconds, which will inevitably lead to timeout. Then we can reflect the advantages of the double pointer algorithm.
Double pointer algorithm
How does the double pointer algorithm deal with data?
When we analyze the traditional processing methods, we will find that for the determined value in each u vector, we have to compare each value in v mindlessly. If i order the index es in the two vectors from small to large, if the subscript of the current U vector (set to i) is greater than that of the v vector (set to j) At this time, i should move J to the same position as i to make a comparison, so that i can ignore those values in the middle, that is, my j value follows the value of i. in this way, i and J can only traverse the array once, so that the traditional algorithm of \ (O(n^2) \) can be optimized to \ (O(n) \) If you can't understand my above description, think about the code. If you can't understand the code, wait until i have time to write what is a double pointer algorithm.
code
#include <bits/stdc++.h> using namespace std; const int N = 5e5 + 10; pair<int, int> u[N], v[N]; //Here, pair can be regarded as a structure with two elements, but it is different from the structure defined by itself int n, a, b; int main() { cin >> n >> a >> b; for (int i = 0; i < a; i++) { cin >> u[i].first >> u[i].second; } for (int i = 0; i < b; i++) { cin >> v[i].first >> v[i].second; } sort(u, u + a ); sort(v, v + b ); long long res = 0; for (int i = 0, j = 0; i < a && j < b; i++) { while (j < b && v[j].first < u[i].first)j++; if (j >= b)break; if (u[i].first == v[j].first)res += u[i].second * v[j].second; } cout << res; return 0; }
Discretization approach
Disclaimer: I didn't write the code here, but I can't find the original author's blog address. When I find it, I'll add it, such as invasion and deletion.
/* Sparse vector */ #include <iostream> #include <map> using namespace std; map<int, int> mp; int main() { int n, m1, m2; long long ans = 0; cin >> n >> m1 >> m2; for (int i = 0; i < m1; i++) { int num1, num2; cin >> num1 >> num2; mp[num1] = num2; } for (int i = 0; i < m2; i++) { int num1, num2; cin >> num1 >> num2; ans += mp[num1] * num2; } cout << ans; } /* 10 3 4 4 5 7 -3 10 1 1 10 4 20 5 30 7 40 */
Summary
- The double pointer algorithm can optimize the traditional double traversal
- Pay attention to the difference between pair and self-defined structure
- Learn to use map to realize discretization, so you don't have to write discretization functions yourself
Last words
In fact, this question is not difficult (see after writing), but I can't successfully realize my ideas in the process of writing. I have tried double pointer and discretization, but I still can't write it. I wanted to write about the pit I stepped on, but there was no time (blogging really takes a lot of time) , I'll relax a little later. Let's watch it. In fact, I've written the pit in the summary. You can learn it by checking the data. OK, that's all for today. Bye!