Example | table | Answer |
0 | {1,1,2,3, 1,0,3,2, 2,0,1,3, 1,2,3,0} |
2 (the set is {0,1}) |
1 | {0,1,2,3, 1,2,3,0, 2,3,0,1, 3,0,1,2} |
1 (the set is {0}) |
2 | {1,1,1,1, 2,2,2,2, 3,3,3,3, 0,0,0,0} |
4 (the set is {0,1,2,3}) |
3 | {0} |
1 (the set is {0}) |
Let's first wrap our heads around the problem. Let's define CS(x) to be the smallest closed subset that contains x. We can build CS(x) incrementally, in the following way:
- for every value of x # There are n of these - Calculate CS(x) # This will take n passes, because we add one element each time. - By enumerating all pairs in CS(x) # There are n^2 pairs - For each pair, you insert into a set. # This is log(n) - - -That's O(n4log(n)) which is pretty slow. I didn't test it against Topcoder, because I couldn't bring myself to write such a slow program. However, it is a sound approach -- we just need to make it faster.
A big problem with the approach above is that it doesn't remember which pairs that it has already processed. For example, if you've already calculated 0*0 once, you don't need to calculate it again.
Here's an approach to reduce the running time. Once again, we are going to calculate CS(x) incrementally. We are going to maintain three data structures:
- for every value of x - Each potential element of CS(x) is only ever inserted into CS(x) once. - Each product i*j is only calculated once. - Each product is only ever inserted into Next_To_Add once. -This yields a running time of O(n3log(n)). Think of it as: