NOI杂题选做

注:这篇文章按照题目年份来排序。由于本人代码较为松散,放上代码会占用较多空间,因此选择放测评链接。

2018

D1T2 冒泡排序

由于这是这篇博文的第一个记录的题,所以写的比较详细。

好像我们在去年暑假考NOI套题的时候就做过这道题,只不过当时我 $ \text{next_permutation} $ 了而已。

现在回头来看这道题,还是非常巧妙的。

首先,我们需要找到什么样的排列能满足其交换次数达到下界,这也应该是我们第一个想到的切入点。

那么我们应该想到,满足交换次数达到下界的排列必然不可能含有一个长度 \(\geq 3\) 的下降子序列,因为如果含有一个长度 \(\geq3\) 的下降子序列,那么第二个元素在与第一个元素交换完后,必然会与第三个元素交换造成“走远路”的情况,那么是肯定不能满足交换次数到达下界的条件的。

那么是不是所有不含长度 \(\geq 3\) 的下降子序列的排列都能让交换次数达到下界呢?答案是肯定的。至于证明,我个人认为题解区里面\(\text{shadowwice}\)的证明给的简单明了,可以作参考(我也是看那个才看懂的)。

那么现在先不考虑字典序的限制,答案如何计算呢?

我们不妨这样想,设当前已经放置的最大值为 \(j\),那么我们定义“限制元素”表示还没有填的值小于 \(j\) 的元素。

显然,限制元素必须按顺序填入,否则即非法。

如果我们在这一个位置上填上第 \(k\) 个非限制元素,那么非限制元素的数量将会减少 \(k\) 个。如果填上限制元素,那么将不会有变化。

我们可以设 \(f_{i,j}\) 表示当前剩下 \(i\) 个元素,其中有 \(j\) 个是非限制元素。 显然能得到下式:

\[f_{i,j} = \sum\limits_{k = 0}^{j} f_{i - 1, j - k} (f_{0, 0} = 1) \]

可以发现,这个东西其实就是两个组合数相减。

\[f_{i, j} = C_{i + j - 1}^{j} - C_{i + j - 1}^{j - 2} \]

那么我们在预处理阶乘及阶乘逆的情况下容易 \(O(1)\) 求出 \(f_{x, y}\)

其实, \(f_{n, n}\) 就是卡特兰数 \(C(n)\)

然后我们再来考虑有限制的情况。 设当前做到第 \(i\) 位, 还剩余的非限制元素数目为 \(cnt\), 在它前面比他小的数有 \(b\) 个, 后面有 \(c\) 个比它大。

我们可以让 \(cnt\)\(c\) 取个min, 因为填入这一位后的 \(cnt\) 必然不大于 \(c\)

首先我们考虑这一位填入的 \(p_i > a_i\) 时的情况,如果此时 \(cnt = 0\) ,那么意味着后面的元素必然只能按顺序排列,这个排列的字典序是严格不大于给定排列的(此时前面填入的元素完全相同),那么就可以break了。

否则, 答案就会加上 \(f_{n - i + 1, cnt - 1}\) ,这个可以 \(O(1)\) 计算。

那么再考虑 \(p_i= a_i\) 的情况。首先,如果 \(c\) 更新了 \(cnt\) 的值,说明这一位一定是填入了一个非限制元素,所以必然合法。

另一种情况是, \(a_i\) 是当前未填入的非限制元素的最小值,即 \(a_i = b + 1\) 这个时候也是合法的。

否则,就可以直接 \(\text{break}\) 了。

瓶颈是求出 \(b\)\(c\) ,这个可以使用树状数组进行维护。 时间复杂度 \(O(n \log n)\)

测评记录

posted @ 2023-02-10 21:29  _LiMLE  阅读(24)  评论(0)    收藏  举报