Official

E - Ascendant Descendant Editorial by evima


For each \(i\), consider the maximal interval \([L_i, R_i]\) that satisfies the following conditions:

  • \(L_i \leq i \leq R_i\)
  • For each \(j \in [L_i, R_i]\), vertex \(A_i\) is an ancestor of vertex \(B_j\) (or \(A_i = B_j\)).

The idea is that \([L_i, R_i]\) represents the range within which \(A_i\) can seemingly move. However, there are positions within this range where \(A_i\) actually cannot move, so we need to account for that.

First, an important property is that the set of intervals \([L_i, R_i]\) is laminar. In other words, these intervals do not partially overlap and form a tree-like structure.

We proceed in descending order of \(A_i\), that is, in ascending order of size of \([L_i, R_i]\). Within the range \([L_i, R_i]\), where \(A_i\) can seemingly move, we calculate the range where \(A_i\) can actually move. To do this, we need to manage the positions that are already “fixed.” Here, “fixed” positions are defined as follows:

  • Suppose there are \(k\) intervals that fall within the subtree of the interval \([L_i, R_i]\) (in the tree structure of the intervals). If \(R_i - L_i + 1 = k\) holds, then the values corresponding to these \(k\) intervals will fill the entire \([L_i, R_i]\). After this, no other values will be allowed to enter \([L_i, R_i]\). At this point, we call the positions within \([L_i, R_i]\) “fixed.”

When processing \([L_i, R_i]\), it is necessary to shrink this interval so that it does not include the fixed positions. Let \([l, r]\) denote the resulting interval. In fact, \(A_i\) can move to any position within \([l, r]\). This is because the positions where \(A_i\) cannot move are exactly the fixed positions defined above.

Although we say \(A_i\) can move to any position within \([l, r]\), the actual available positions are those not occupied by the previously processed values. The number of positions occupied by those values is constant, regardless of how we have placed them. Therefore, the number of candidates for the position where the current \(A_i\) can be placed is determined. By considering this for all \(A_i\), we can determine how many different sequences \(A\) can be formed in the end. However, note that if there are duplicate values in \(A_i\), it is necessary to divide by an appropriate factor.

By implementing the above steps, this problem can be solved. The most likely bottleneck is finding \(L_i\) and \(R_i\). This can be done, for example, by using binary search and interval LCA queries on \(B\). The interval LCA query can be processed in \(O(\log M + \log N)\) time by maintaining the min/max of the dfs-order of the vertices within the interval.

Summarizing the above, the time complexity is \(O(N + M\log M(\log M + \log N))\). Furthermore, if you handle the interval min query and LCA query in \(O(1)\) time, you can reduce one \(\log\) from the time complexity.

Sample Code (C++)

posted:
last update: