题目
题意概要
对排列
{
a
}
\{a\}
{a},每次将其中的前缀
max
\max
max 放到序列末尾(保持原顺序),问多少次能够完成排序。
数据范围与提示
n
⩽
2
×
1
0
5
n\leqslant 2\times 10^5
n⩽2×105 。
思路
类似 0-1 principle \text{0-1 principle} 0-1 principle,较小数对大数的相对顺序无影响,可暂时忽略。所以,应该只需要考虑 某个值域后缀中数字。为了方便,就用原序列 [ 1 , n ] [1,n] [1,n] 作为指代;它实际上是 [ x , n ] [x,n] [x,n],但 x x x 和 1 1 1 地位相同。
考虑将数字 1 1 1 去掉,得到的序列需要 t t t 次才能完成排序,即 [ 2 , n ] [2,n] [2,n] 的相对顺序正确。则原序列要么 t t t 次就完成排序,要么 ( t + 1 ) (t{+}1) (t+1) 次完成排序。
如何判断?最 n a i v e \rm naive naive 想法是,找到 1 1 1 此时位置。这不可能。它相当于维护整个序列的模样。如果能做到,就直接模拟了,还考虑啥呀!
看来不应求出绝对位置。或许只需判断 1 1 1 在 2 2 2 之前或是之后。然而也无迹可寻。
不知道这条性质与下面的构造,哪个是先被想出的:非首项做为前缀 max \max max 出现后,永远不会成为首项。下一段给出证明。为了方便叙述,称前缀 max \max max 元素为 H ( high ) {\frak H}\;(\textrm{high}) H(high) 类数。
首项是 H \frak H H 类数。因此,若非首项元素 f f f 是 H \frak H H 类数,前面必有更小的 H \frak H H 类数 v v v 。二者操作后相邻。想要 f f f 成为首项,需要把 v v v 移开。只能期待 v v v 不是 H \frak H H 类数而 f f f 是。而这仍是非首项元素 f f f 是 H \frak H H 类数的情况,所以它前面仍有比自己更小的数。这就说明不可能了。
证明了这个,出题人就构造了个辅助数字:记 f f f 为 [ 2 , n ] [2,n] [2,n] 中的数字在 ( t − 1 ) (t{-}1) (t−1) 时刻最靠前的那个。不难验证 f ≠ 2 f\ne 2 f=2,因为此时再进行一次操作就能让 [ 2 , n ] [2,n] [2,n] 有序,且现在无序。根据定义, 2 2 2 在 f f f 之后。 1 1 1 就有可能在 f f f 之前、二者之间、 2 2 2 之后。
想要答案为 t t t,不难验证必须是 1 1 1 在 f f f 和 2 2 2 之间(不会在把 f f f 放到 2 2 2 后面的同时把 1 1 1 给带走)。只有 D D G \sf DDG DDG 的双眼才能看到下面这条判据——正是这双眼睛,把 O n e I n D a r k \sf OneInDark OneInDark 看得只有 18 c m 18\rm cm 18cm 高——三者的 圆排列 顺序不变。也就是说,认为 ⟨ a , b , c ⟩ \langle a,b,c\rangle ⟨a,b,c⟩ 和 ⟨ b , c , a ⟩ \langle b,c,a\rangle ⟨b,c,a⟩ 相等,则 ⟨ 1 , 2 , f ⟩ \langle 1,2,f\rangle ⟨1,2,f⟩ 在 t t t 时刻之前亘古不变。而这也恰好足够确定 1 1 1 是否在 2 , f 2,f 2,f 之间,巧妙至极!
证明则只需要耐心。记非
H
\frak H
H 类数字为
L
(
low
)
{\frak L}\;(\textrm{low})
L(low) 类数字。循环顺序改变,必然是从左到右
H
,
low
,
H
{\frak H},\textrm{low},{\frak H}
H,low,H 或
L
,
high
,
L
{\frak L},\textrm{high},{\frak L}
L,high,L 。当
f
f
f 为首项时,其为
H
\frak H
H,而
1
,
2
1,2
1,2 都是
L
\frak L
L 了,无矛盾。当
f
f
f 不是首项时,由 性质
知其为
L
\frak L
L,尝试填出
L
,
high
,
L
{\frak L},\textrm{high},{\frak L}
L,high,L 会失败,另一种更会失败。
所以只需判断最初序列中 ⟨ f , 1 , 2 ⟩ \langle f,1,2\rangle ⟨f,1,2⟩ 是否为这种圆排列,就可以得到新的 t ′ t' t′ 了。而 f f f 的更新也同样简单,若 t t t 不变则 f f f 不变(因为此时顺序为 ⟨ f , 1 , 2 ⟩ \langle f,1,2\rangle ⟨f,1,2⟩,非圆排列),否则 f = 2 f=2 f=2,即 t ′ − 1 = t t'-1=t t′−1=t 时刻的情况。
代码
注意 t = 0 t=0 t=0 时不应递推,因为 f f f 未定义。这样困难的题目,代码却寥寥数行……
#include <cstdio> // JZM yydJUNK!!!
int pos[200005];
int main(){
int n; scanf("%d",&n);
for(int i=1,x; i<=n; ++i)
scanf("%d",&x), pos[x] = i;
int t, f = n, j = n-1;
for(; j&&pos[j]<=pos[f]; --j) f = j;
if(!j) return void(puts("0")), 0;
for(t=1; j!=1; --j) // only one operation needed
if(!(pos[j] < pos[f] && (pos[j-1] < pos[j] || pos[f] < pos[j-1]))
&& !(pos[f] < pos[j] && pos[f] < pos[j-1] && pos[j-1] < pos[j]))
++ t, f = j; // j is 2 in solution
printf("%d\n",t);
return 0;
}