Codeforces-1688 C: The Third Problem
题目传送门:Codeforces-1688 C: The Third Problem
题目
题目截图
样例描述
题目大意
给定一个
0
0
0 到
n
n
n 的排列
a
a
a。任务是找到多少个排列
b
1
,
b
2
,
⋯
,
b
n
b_1, b_2, \cdots, b_n
b1,b2,⋯,bn 与
a
a
a 相似。
两个排列相似指两个排列的任意区间
[
l
,
r
]
[l,r]
[l,r] 上的子区间的
MEX
\text{MEX}
MEX 值相同。
MEX
\text{MEX}
MEX 值是指数组未出现的最小的非负整数。
题目解析
首先很容易想到
0
0
0。除了包含
0
0
0 的区间,其它区间的
MEX
\text{MEX}
MEX 值必然为
0
0
0,这也意味着,
0
0
0 的位置在
a
、
b
a、b
a、b 中应该是相同的。
我们更近一步地思考
0
,
1
0,1
0,1。显然,同上,
1
1
1 的位置也应该是相同的。
我们更近一步地思考
0
,
1
,
2
0,1,2
0,1,2。此时却与上面的情况不同,固定住
pos
0
,
pos
1
\text{pos}_0,\text{pos}_1
pos0,pos1可以分为两种情况:
(1)
a
a
a 中
2
2
2 在
[
pos
0
,
pos
1
]
[\text{pos}_0, \text{pos}_1]
[pos0,pos1] 之内。这种情况下,
b
b
b 中
2
2
2 在
[
pos
0
,
pos
1
]
[\text{pos}_0, \text{pos}_1]
[pos0,pos1] 的移动并不会改变
MEX
\text{MEX}
MEX 的分布情况。因为若我们不考虑区间外,对于区间内,不论
2
2
2 的位置如何移动,只有包含
0
,
1
,
2
0,1,2
0,1,2,
MEX
\text{MEX}
MEX 值才有进一步增长的可能。而区间外的
MEX
\text{MEX}
MEX 值实际上也没有变化。
(2)
a
a
a 中
2
2
2 在
[
pos
0
,
pos
1
]
[\text{pos}_0, \text{pos}_1]
[pos0,pos1] 之外。这种情况下,
b
b
b 中
2
2
2 不可移动,因为一旦移动,就会造成
MEX
\text{MEX}
MEX 分布的变化。比如
a
=
[
0
,
1
,
2
,
3
]
a = [0,1,2,3]
a=[0,1,2,3] 和
b
=
[
0
,
1
,
3
,
2
]
b=[0, 1, 3, 2]
b=[0,1,3,2],在
a
2
=
2
,
b
2
=
3
a_2=2,b_2=3
a2=2,b2=3 处的
MEX
\text{MEX}
MEX 值是不同的。
我们更近一步地思考
0
,
1
,
2
,
3
0,1,2,3
0,1,2,3。我们假设
0
,
1
,
2
0,1,2
0,1,2 已经固定,去看
3
3
3 能够放在哪些位置。显然此时我们要考虑的区间是
[
min
(
pos
0
,
pos
1
,
pos
2
)
,
max
(
pos
0
,
pos
1
,
pos
2
)
]
=
[
l
,
r
]
[\min(\text{pos}_0,\text{pos}_1,\text{pos}_2),\max(\text{pos}_0,\text{pos}_1,\text{pos}_2)]=[l,r]
[min(pos0,pos1,pos2),max(pos0,pos1,pos2)]=[l,r],如果
3
3
3 不能移动,那我们固定住
3
3
3,如果能移动,我们将答案乘上它能移动的位置数量
(
r
−
l
+
1
−
3
)
(r-l+1-3)
(r−l+1−3)。(由于整个过程位置是无放回的,我们要减去已经存在的位置,前面有三个位置已经被固定住了)
显然这个过程是可以循环的。于是我们不断的向
b
b
b 中添数,固定,添数。。。在添数的时候把答案乘上那个数的可移动位置数量即可。
Code
#include <bits/stdc++.h>
using namespace std;
const int mod = 1e9 + 7;
const int maxn = 1e5 + 7;
int pos[maxn];
int main() {
int T, n, x;
cin >> T;
while(T--) {
cin >> n;
for(int i=0; i<n; ++i)
cin >> x, pos[x] = i;
int ans = 1, l = pos[0], r = pos[0];
for(int i=1; i<n; ++i) {
if(pos[i] < l) l = pos[i];
else if(pos[i] > r) r = pos[i];
else ans = (1ll * ans * (r - l + 1 - i)) % mod;
}
cout << ans << endl;
}
return 0;
}