Editorial for Valentine's Day '19 S5 - A Top Tree Problem


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: Ninjaclasher

There were many solutions to this problem. We will describe one of them here.

For the first subtask, we can brute force the queries. For each query, we can run a DFS from u_1 to u_2, marking all nodes on its path as visited. Then, we run another DFS from u_2 to u_3, and so on. If at any point, a node that has been visited is revisited, then there is no simple path, and the answer to the query is 0.

Time Complexity: \mathcal{O}(NQk)


For the second subtask, we can use Lowest Common Ancestor (LCA). Let us say that the tree is rooted at node 1. Notice that any simple path in a rooted tree has a nonnegative length segment that traverses up the tree, and then a nonnegative length segment that traverses down the tree. Also notice that the point at which it switches direction is the LCA of the end nodes of the path.

We can use this property to answer the queries.

Let lca be the LCA of nodes u_1 and u_k. To answer the query, we can loop through u. If LCA(u_i, u_{i+1}) = u_{i+1}, then we are still traversing up the tree. Otherwise, if LCA(u_i, u_{i+1}) = lca, then this segment of the path contains the node at which the path switches direction. Thus, after this segment, all future segments should traverse down the tree. To check if a segment traverses down the tree, we can check if LCA(u_i, u_{i+1}) = u_i. If at any point, these conditions are not satisfied, then there is no simple path, and the answer to the query is 0.

Time Complexity: \mathcal{O}(Qk \log N)


For the last subtask, we will describe the solution that is the easiest to prove.

Let us decompose the tree with heavy-light decomposition (HLD). We will use a lazy segment tree to store path information, including the maximum value, and the index of the maximum value. An element i in the segment tree stores the number of times node i is visited while traversing from u_1 \dots u_k.

For each query, we can perform k range increments on the segment tree. We can do a path increment from u_1 to u_2, another path increment from u_2 to u_3, etc. Be careful to only increment u_i once. Notice from the two range increments given, u_2 might be incremented twice, but it should only be incremented once. Notice that if the maximum in the segment tree is ever greater than v+1, not enough edges can be added to reduce the number of times that node is visited to \le 1, and so the answer is 0.

To check the answer to a query is 1, we can try to "collapse" v segments of the path. By storing the maximum value, and the index of the maximum value, we can easily figure out which of the k segments we should attempt to "collapse".

Observe that if an edge were to be inserted, it is always optimal to insert the edge between two nodes that are in u. The proof is left as an exercise for the reader.

Let node W be one of the nodes with the maximum value, and the one that was stored in the segment tree. The reason we only need to keep track of one of the indices is that the optimal solution will always collapse a segment that traverses through W. Otherwise the answer to the query would be 0. We can loop through the segments. For each segment that W is on, we can try to collapse it by range decrementing the segment tree. Checking if a node is on a path is trivial, and is left as an exercise for the reader (Hint: read the editorial for subtask two).

If the maximum is still greater than 1 (at least one node is visited more than once), and v = 2, we can try to collapse another segment the same way as described above. Note that although it may look like there are k^v segments that will be tested, there are actually only on the order of v^v segments, as there is an upper bound from the fact that if the maximum value in the segment tree is greater than v+1, then the answer to the query is always 0.

The answer to a query would be 1 only if the segment tree's maximum value is \le 1 after collapsing up to v segments.

Time Complexity: \mathcal{O}(Q \times (k+v^v) \log^2 N)

Note: There does exist a non-HLD solution, which has a time complexity of \mathcal{O}(Q \times k^v \log N), but it will not be covered in this editorial.


Comments

There are no comments at the moment.