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 aa of length nn, find how many permutations bb of the same length are similar to aa.

If, for every interval [l,r](1lrn)[l, r] (1 \le l \le r \le n), the following condition holds:

MEX(al,al+1,,ar)=MEX(bl,bl+1,,br)\operatorname{MEX}(a_l, a_{l + 1}, \ldots ,a_r) = \operatorname{MEX}(b_l, b_{l + 1}, \ldots ,b_r)

then permutations aa and bb are called similar.

Here, for an array cc, MEX\operatorname{MEX} is defined as the smallest non-negative integer xx that does not appear in cc.

For example, MEX([1,2,3,4,5])=0\operatorname{MEX}([1,2,3,4,5]) = 0 and MEX([0,1,2,4,5])=3\operatorname{MEX}([0,1,2,4,5]) = 3.

Because the answer may be large, print it modulo 109+710^9 + 7.

Approach

It may be difficult to think of the answer directly, so first simulate the sample and try to construct some bb.

a=[1,3,7,2,5,0,6,4]a = [1, 3, 7, 2, 5, 0, 6, 4]

Begin by considering the number 00 in the sample. We can see that the position of 00 in bb must be the same as its position in aa.

Let the position of ii in aa be posi\text{pos}_i; for example, pos0=6\text{pos}_0 = 6 (indices start from 1).

Compare the MEX values of aa and bb on the interval [pos0,pos0][\text{pos}_0, \text{pos}_0]. In aa, because a[pos0]=0a[\text{pos}_0] = 0, we have MEX([pos0])=1\operatorname{MEX}([\text{pos}_0]) = 1.

If the position of 00 in bb changed, then because a[pos0]>0a[\text{pos}_0] > 0, the MEX of this interval in bb would be 00.

Thus, the position of 00 cannot change.

We can also conclude that the position of 11 cannot change.

Consider the intervals [pos1(1),pos0(6)](1 3 7 2 5 0)[\text{pos}_1(1), \text{pos}_0(6)] (1\ 3\ 7\ 2\ 5\ 0) and [pos1+1,pos0](3 7 2 5 0)[\text{pos}_1 + 1, \text{pos}_0](3\ 7\ 2\ 5\ 0).

Because 11 is present, MEX([pos1,pos0])\operatorname{MEX}([\text{pos}_1, \text{pos}_0]) is greater than 11. Because 00 is present and 11 is absent, MEX([pos1+1,pos0])\operatorname{MEX}([\text{pos}_1 + 1, \text{pos}_0]) is exactly 11.

Suppose that we changed the position of 11 in bb, for example moving it to position 22. Then MEX([pos1+1,pos0](1 7 2 5 0)\operatorname{MEX}([\text{pos}_1 + 1, \text{pos}_0](1\ 7\ 2\ 5\ 0) in bb would be greater than 11, which does not match the value 11 in aa.


Now consider where 22 can be placed legally. If 2(pos1,pos0)2 \in (\text{pos}_1, \text{pos}_0) in aa, then in bb, 22 can be placed at any position in the interval (pos1,pos0)(\text{pos}_1, \text{pos}_0).

Let [l,r][l, r] be an interval in aa containing 00 and 11, namely lpos1,pos0rl \le \text{pos}_1, \text{pos}_0 \le r.

Because 2(pos1,pos0)2 \in (\text{pos}_1, \text{pos}_0) in aa, every such interval has MEX greater than 22 (an interval containing both 00 and 11 also contains 22).

At the same time, every other interval in aa that does not satisfy lpos1,pos0rl \le \text{pos}_1, \text{pos}_0 \le r has MEX at most 11 (such an interval contains at most one 00, so its MEX is 11).

Therefore, as long as 2(pos1,pos0)2 \in (\text{pos}_1, \text{pos}_0) in bb, we still have MEX([l,r])>2\operatorname{MEX}([l,r]) > 2. Keeping every other number in place preserves similarity between aa and bb.

There are (pos0pos1+1)2(\text{pos}_0 - \text{pos}_1 + 1) - 2 such positions; the 2-2 accounts for the positions already occupied by 00 and 11.


What if 2(pos1,pos0)2 \notin (\text{pos}_1, \text{pos}_0) in aa?

For example, a=[1,3,7,6,0,5,2,4]a = [1, 3, 7, 6, 0, 5, 2, 4].

As with 00 and 11, we can conclude that, in this case, 22 must be placed at the same position in bb.

Consider [pos1,pos2][\text{pos}_1, \text{pos}_2], whose MEX is greater than 22, and [pos1,pos21][\text{pos}_1, \text{pos}_2 - 1], whose MEX is exactly 22 (it contains 00 and 11).

If we place 22 at pos21\text{pos}_2 - 1, the MEX of [pos1,pos21][\text{pos}_1, \text{pos}_2 - 1] becomes greater than 22.

In a=[1,3,7,6,5,0,2,4]a = [1, 3, 7, 6, 5, 0, 2, 4], we can place 33 anywhere in (pos1,pos2)(\text{pos}_1, \text{pos}_2). Only in this way can we ensure MEX[l,r]>3\operatorname{MEX}[l,r] > 3 whenever lpos0,pos1,pos2rl \le\text{pos}_0, \text{pos}_1, \text{pos}_2 \le r, while all other intervals have MEX less than 33.

In other words, if an interval in aa contains every number smaller than 33, it must contain 33. Equivalently, there cannot be an interval whose MEX is 33, so we need 3(pos1,pos2)3 \in (\text{pos}_1, \text{pos}_2).

Let x=min[pos0pos3]x = \min{[\text{pos}_0 \ldots \text{pos}_3]} and y=max[pos0pos3]y = \max{[\text{pos}_0 \ldots \text{pos}_3]}. The number of positions satisfying 3(pos1,pos2)3 \in (\text{pos}_1, \text{pos}_2) is (yx+1)3(y - x + 1) - 3; the 3-3 accounts for the positions already occupied by 020 \sim 2.


We can generalize this observation. If a number in aa 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 kk, x=min[pos0posk]x = \min{[\text{pos}_0 \ldots \text{pos}_k]}, and y=max[pos0posk]y = \max{[\text{pos}_0 \ldots \text{pos}_k]}. If kk is outside [x,y][x,y], it can only be placed at posk\text{pos}_k; otherwise, it can be placed in any unoccupied position in [x,y][x,y].

Let did_i be the number of positions available for each number. The final answer is the product of all dd, namely i=0n1\prod_{i = 0}^{n - 1}.

Code

In the implementation, consider the numbers from 00 onward one by one. This conveniently determines the xx and yy mentioned above and the number of occupied positions in [x,y][x,y].

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
#include <bits/stdc++.h>
using namespace std;
#define ll long long
// keywords:
const int MOD = 1e9 + 7;
int main() {
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];
else if (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.