Editorial for OCC '19 G4 - Willson and Fighting
Submitting an official solution before solving the problem yourself is a bannable offence.
Author:
For subtask 1, the intended solution is to do exactly what is described in the problem statement. That is, for all pairs of geese, if they both honk at each other, then increment the answers for both of the geese. There are pairs to search through.
Time complexity:
For the other subtasks, it is helpful to find an algorithm that can be optimized from to a better time complexity. The algorithm is as follows.
The input contains geese. Each goose can be described by a 2D point and a honking radius. Next, sort the geese by increasing radius, and rotate the coordinate system by .
The geese are sorted by increasing radius, and each goose is described by a point and a square. There is no need to keep track of which pairs of geese are mates. In the rest of this editorial, "Goose " will refer to the goose in the sorted list of geese. Also, goose is described by "point " and "square ".
To get the answer for goose , simply loop through all of the that fit into these 2 cases.
Case 1, . In this case, goose 's radius is less than or equal to goose 's radius. The following are equivalent conditions:
- Goose will fight with goose .
- Goose is honking at goose .
- Point is strictly inside square .
In summary, if point is in square , then increment the answer for goose .
- Case 2, . In this case, goose 's radius is greater than or equal to goose 's radius. If point is strictly inside square , then increment the answer for goose .
It takes time to get the answer for goose . Overall, this algorithm is .
Time complexity: with a better constant
For subtask 2, the intended solution is to optimize the previous solution to run in sub- time.
In the naive solution, case 1 will occur times. There is a way to do all of the case 1's in sub- time. Design a data structure that supports the following:
- Insert a 2D point.
- Query a rectangle. Return the number of points that are inside the rectangle.
Then use the data structure like this. Query square , insert point , query square , insert point , etc.
The data structure can be implemented with a 2D segment tree that uses memory. Insertion is and query is . Overall, the case 1's will take time.
Similarly, to do the case 2's in sub- time, design a data structure that supports the following:
- Insert a rectangle.
- Query a 2D point. Return the number of rectangles that the point is in.
Again, the data structure can be a 2D segment tree.
At this point, all of the case 1's and case 2's are handled. It is time to print the answer.
Time complexity:
Memory complexity:
For subtask 3, the intended solution is to memory optimize the subtask 2 solution. However, the author strongly dislikes 2D segment trees, so he used a different approach to solve subtask 3.
Consider a function . This function will solve all of the case 1's and case 2's among the geese in the range . The first observation is to use divide and conquer in the following way:
- If there are fewer than 2 geese in , then nothing needs to be done.
- Split the range into the two ranges and .
- Do the case 1's where goose is in and goose is in .
- Do the case 2's where goose is in and goose is in .
- Call and . This will do the remaining case 1's and case 2's.
(Insert a diagram when I have time. Maybe it can help the reader visualize what's happening.)
The idea is to get the answer by running on the entire list of geese.
The second observation is that the case 1's can be done quickly. First, insert all of the points in . Next, query all of the squares in . This can be done with line sweep, and a 1D segment tree that supports the following:
- Insert a 1D point.
- Query a line segment. Return the number of points in this line segment.
- Reset. That is, remove all 1D points from the data structure.
The line sweep will generate events, and it takes time to sort them. In the 1D segment tree, insertion is and query is . Overall, the time complexity to solve the case 1's is .
(Note: It is possible to use a BIT instead of a 1D segment tree. The time complexity is the same.)
The third observation is that the case 2's can be done quickly with line sweep. The approach is similar. The time complexity is also .
At this point, the algorithm is complete. The time complexity of the algorithm can be described as:
The comes from recursion. The comes from creating and sorting the events. The comes from the 1D segment tree.
The time complexity simplifies to .
Time complexity:
Memory complexity:
Fun fact: This problem was originally supposed to be tle17c7p5, but my algorithm turned out to be incorrect, and a different problem had to be used for the contest.
Comments