Editorial for CCC '22 S4 - Good Triplets


Remember to use this editorial only when stuck, and not to copy-paste code from it. Please be respectful to the problem author and editorialist.
Submitting an official solution before solving the problem yourself is a bannable offence.

Author: d

For the first subtask, it suffices to follow the definition of a good triplet. Firstly, there are O(N3) ways to select (a,b,c). Secondly, consider the condition that the origin is strictly inside the triangle. This is equivalent to saying that Pa, Pb, and Pc divide the circle into 3 arcs, and each arc is strictly shorter than C2. This leads to the following approach. Sort the positions so that PaPbPc, then check that

PbPa<C2, PcPb<C2, and (Pa+C)Pc<C2.

For example, the first of these checks can be implemented in code as P[b]-P[a] < (C+1)/2 in C++ or Java, or P[b]-P[a] < (C+1)//2 in Python 3.

For the second subtask, the goal is to find a solution that works well when C is small. Let Lx be the number of points drawn at location x. If three locations i,j,k satisfy the second condition, we want to add Li×Lj×Lk to the answer. This approach is O(N+C3) and is too slow. However, we can improve from three nested loops to two nested loops. If i and j are chosen already, either k does not exist, or k is in an interval. It is possible to replace the third loop with a prefix sum array. This algorithm's time complexity is O(N+C2).

It is possible to optimize this approach to O(N+C) and earn 15 marks. The idea is to eliminate both the j and k loop. Start at i=0 and compute Lj×Lk in O(C) time. The next step is to transition from i=0 to i=1, and to maintain Lj×Lk in O(1) time. This requires strong familiarity with prefix sum arrays. Care with overflow and off-by-one errors is required.


Comments


  • 23
    neynt  commented on March 6, 2022, 4:36 p.m. edited

    I found this problem a lot easier to think about if you count triplets of points that don't form a triangle and subtract that from the total number of triplets. These are exactly the triplets whose points all belong on a closed half of the circle, so sweeping two pointers along the circle suffices to do this in O(N+C) time.