The content below was generated entirely by machine translation. Please verify its accuracy. If anything is unclear, consult the Chinese source version.
Problem links: (CF, Luogu) | I strongly recommend reading it on the blog.
This problem is genuinely difficult to think of. I spent a long time reading the Codeforces solution before understanding it (I am too inexperienced).
Problem Statement
Given a permutation a of length n, find how many permutations b of the same length are similar to a.
If, for every interval [l,r](1≤l≤r≤n), the following condition holds:
MEX(al,al+1,…,ar)=MEX(bl,bl+1,…,br)
then permutations a and b are called similar.
Here, for an array c, MEX is defined as the smallest non-negative integer x that does not appear in c.
For example, MEX([1,2,3,4,5])=0 and MEX([0,1,2,4,5])=3.
Because the answer may be large, print it modulo 109+7.
Approach
It may be difficult to think of the answer directly, so first simulate the sample and try to construct some b.
a=[1,3,7,2,5,0,6,4]
Begin by considering the number 0 in the sample. We can see that the position of 0 in b must be the same as its position in a.
Let the position of i in a be posi; for example, pos0=6 (indices start from 1).
Compare the MEX values of a and b on the interval [pos0,pos0]. In a, because a[pos0]=0, we have MEX([pos0])=1.
If the position of 0 in b changed, then because a[pos0]>0, the MEX of this interval in b would be 0.
Thus, the position of 0 cannot change.
We can also conclude that the position of 1 cannot change.
Consider the intervals [pos1(1),pos0(6)](137250) and [pos1+1,pos0](37250).
Because 1 is present, MEX([pos1,pos0]) is greater than 1. Because 0 is present and 1 is absent, MEX([pos1+1,pos0]) is exactly 1.
Suppose that we changed the position of 1 in b, for example moving it to position 2. Then MEX([pos1+1,pos0](17250) in b would be greater than 1, which does not match the value 1 in a.
Now consider where 2 can be placed legally. If 2∈(pos1,pos0) in a, then in b, 2 can be placed at any position in the interval (pos1,pos0).
Let [l,r] be an interval in a containing 0 and 1, namely l≤pos1,pos0≤r.
Because 2∈(pos1,pos0) in a, every such interval has MEX greater than 2 (an interval containing both 0 and 1 also contains 2).
At the same time, every other interval in a that does not satisfy l≤pos1,pos0≤r has MEX at most 1 (such an interval contains at most one 0, so its MEX is 1).
Therefore, as long as 2∈(pos1,pos0) in b, we still have MEX([l,r])>2. Keeping every other number in place preserves similarity between a and b.
There are (pos0−pos1+1)−2 such positions; the −2 accounts for the positions already occupied by 0 and 1.
What if 2∈/(pos1,pos0) in a?
For example, a=[1,3,7,6,0,5,2,4].
As with 0 and 1, we can conclude that, in this case, 2 must be placed at the same position in b.
Consider [pos1,pos2], whose MEX is greater than 2, and [pos1,pos2−1], whose MEX is exactly 2 (it contains 0 and 1).
If we place 2 at pos2−1, the MEX of [pos1,pos2−1] becomes greater than 2.
In a=[1,3,7,6,5,0,2,4], we can place 3 anywhere in (pos1,pos2). Only in this way can we ensure MEX[l,r]>3 whenever l≤pos0,pos1,pos2≤r, while all other intervals have MEX less than 3.
In other words, if an interval in a contains every number smaller than 3, it must contain 3. Equivalently, there cannot be an interval whose MEX is 3, so we need 3∈(pos1,pos2).
Let x=min[pos0…pos3] and y=max[pos0…pos3]. The number of positions satisfying 3∈(pos1,pos2) is (y−x+1)−3; the −3 accounts for the positions already occupied by 0∼2.
We can generalize this observation. If a number in a lies between all numbers smaller than it, it has many possible positions. If it lies outside all smaller numbers, it can only stay in its original position.
Let the number currently under consideration be k, x=min[pos0…posk], and y=max[pos0…posk]. If k is outside [x,y], it can only be placed at posk; otherwise, it can be placed in any unoccupied position in [x,y].
Let di be the number of positions available for each number. The final answer is the product of all d, namely ∏i=0n−1.
Code
In the implementation, consider the numbers from 0 onward one by one. This conveniently determines the x and y mentioned above and the number of occupied positions in [x,y].
#include<bits/stdc++.h> usingnamespace std; #define ll long long // keywords: constint MOD = 1e9 + 7; intmain(){ int t; cin >> t;
while (t--) { int n; cin >> n; int a[n + 1]; int pos[n + 1]; for (int i = 0; i < n; i++) { cin >> a[i]; pos[a[i]] = i; } ll l = pos[0], r = pos[0]; ll ans = 1; for (int i = 1; i < n; i++) { // l and r are the x and y described above. if (pos[i] < l) l = pos[i]; elseif (pos[i] > r) r = pos[i]; // Outside x and y. else ans = ans * (r - l + 1 - i) % MOD; } cout << ans << endl; } }
Finally, I hope this solution is helpful. If you have any questions, you can contact me through the comments or a private message.