[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}\)
综上,我们得到了:
接下来,我们考虑字典序的问题。
我们枚举一个位置\(i\),前\(i-1\)位和输入序列一样,第\(i\)位比输入序列大。
首先第\(i\)位肯定不能填剩余的最小值。
再然后第\(i\)位不能比前\(i-1\)位最大的小,如果这一位填\(k<mx\),会和剩余最小值组成一个长度为\(3\)的下降子序列。
所以假设剩余有\(k\)个数比前\(i-1\)位最大值小,
则方案数为
注意还要判断一下第\(i\)是否可行,具体看代码。
用树状数组求\(k\),然后我们得到了一个\(O(N^2logN)\)的做法。
考虑优化这个后缀和。
放到网格上来看,就是从\((0,0)\)走到\((i,j)\),每次能向右上,或者下走一次,不能越过\(x\)轴。
向下走有点奇怪,我们变成向右下走,那么就变成了从\((0,0)\)走到\((2i-j,j)\)。
有经验的选手能看出来,这就是卡特兰数。
用组合意义解释,就是在第一次碰到 \(y=-1\) 时,把前面的线段翻折一下。
最后复杂度为\(O(N\log_2N)\)