Official

B - Typical Permutation Descriptor Editorial by evima


For a permutation \((P_1,\dots,P_N)\), here is an algorithm to generate the sequence described in the problem statement:

stack<int> st({0});
P[0] = 0;
vector<int> A(N + 1);
for (int i = 1; i <= N; ++i) {
  while (P[st.top()] > P[i]) st.pop();
  A[i] = st.top();
  st.push(i);
}

Based on this algorithm, we can reformulate the condition: we need to find the number of permutations \((P_1,\dots,P_N)\) such that for each \(i\), the while loop runs until st.back() becomes \(A_i\).

By simulating the behavior of the above algorithm with this reformulation, we can obtain about \(2N\) conditions of the form \(P_i<P_j\). While the answer would be the number of ways to topologically sort this DAG (where these inequalities are considered directed edges), it’s difficult to compute this directly.

So, let’s observe the graph and organize the conditions. First, checking the condition when exiting the while loop for each \(i=1,\dots,N\), we have \(P_i > P_{A_i}\). Considering these inequalities as edges, we get a rooted tree with \(0\) as the root. For each \(i\), all vertices compared with \(i\) during the while loop are in an ancestor-descendant relationship, so by transitivity, only the relationship with the one closest to the root is essential. Summarizing the above, when viewed as a rooted tree, the following two conditions are necessary and sufficient.

When \(v\) has children \(c_1,\dots,c_k\):

  • \(P_{c_i} > P_v\)
  • If \(c_1<\dots<c_k\) then \(P_{c_1} >\dots>P_{c_k}\)

To count permutations satisfying this, we can count valid relative orderings within each subtree that satisfy these conditions. The overall time complexity is \(O(N)\).

Sample Implementation in C++

posted:
last update: