[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}_{ j})-(^{2i-j}_{ j-1}) ]

最后复杂度为(O(NlogN))

原文地址:https://www.cnblogs.com/zzy2005/p/13724128.html