[NOI2018]冒泡排序 (卡特兰数)

首先有一个性质,达到下界的充要条件是排不能存在长度大于\(2\)的下降子序列。
证明:
要想达到下界\(\frac{1}{2}\sum|i-p_i|\),等于每次交换相邻两个数时,这两个数一定是往目的方向移动。
如果存在长度大于\(2\)的下降子序列,那么第一次,对于这个子序列中的中间的一个数\(x\),之前比\(x\)大的数一定会和它产生交换,它就会往前移动,而它又会和后面比它小的数交换,所以它也至少会往后移动一次。所以它一定会在中途产生“掉头”的代价。

有了这个性质后,我们问题变成求不存在长度大于\(2\)的下降子序列的排列数。
\(f_{i,j}\)表示长度为\(i\)的排列,第一个数是\(j\)的方案数。
分几种情况转移:
如果第二个数\(k\)大于\(j\),那么方案数就是\(f_{i-1,k}\)
如果第二个数\(k\)小于\(j\),且不等于\(1\),那么一定会存在为\((j,k,1)\)这样的下降子序列,所以方案数为\(0\)
如果第二个数为\(1\),那么小于\(j\)的数一定是依次排列的(位置可以不连续),且之后的方案我们可以对应一种合法的方案(\(1\)换到\(2\) , \(2\)换到\(3\) ... , \(j-1\)换到\(1\)),所以方案数为\(f_{i-1,j-1}\)
综上,我们得到了:

\[f_{i,j}=\sum_{k=j-1}^{i-1}f_{i-1,k} \]

接下来,我们考虑字典序的问题。
我们枚举一个位置\(i\),前\(i-1\)位和输入序列一样,第\(i\)位比输入序列大。
首先第\(i\)位肯定不能填剩余的最小值。
再然后第\(i\)位不能比前\(i-1\)位最大的小,如果这一位填\(k<mx\),会和剩余最小值组成一个长度为\(3\)的下降子序列。
所以假设剩余有\(k\)个数比前\(i-1\)位最大值小,
则方案数为

\[\sum_{j=k+1}^{n-i+1}f_{n-i+1,j} \]

注意还要判断一下第\(i\)是否可行,具体看代码。
用树状数组求\(k\),然后我们得到了一个\(O(N^2logN)\)的做法。
考虑优化这个后缀和。

\[S_{i,j}=\sum_{k=j}^if_{i,k}=f_{i,j}+\sum_{k=j+1}^if_{i,k}=S_{i-1,j-1}+S_{i,j+1} \]

放到网格上来看,就是从\((0,0)\)走到\((i,j)\),每次能向右上,或者下走一次,不能越过\(x\)轴。
向下走有点奇怪,我们变成向右下走,那么就变成了从\((0,0)\)走到\((2i-j,j)\)
有经验的选手能看出来,这就是卡特兰数。
用组合意义解释,就是在第一次碰到 \(y=-1\) 时,把前面的线段翻折一下。

\[S_{i,j}= {2i-j\choose i-j} - {2i-j\choose i-j-1} \]

最后复杂度为\(O(N\log_2N)\)

posted @ 2020-11-18 16:16  zzy2005  阅读(116)  评论(0编辑  收藏  举报