NOI2018 冒泡排序
NOI2018 D1T2 冒泡排序
求有多少个排列 \(p\),满足字典序严格大于 \(q\),且冒泡排序的交换次数到达下界。
\(n\le 6\times 10^5\)
\(\rm Sol:\)
略微观察,发现到达下界即不存在无用挪动,即每一次交换都会使得两者向着目标方向移动一格。
换而言之,对于 \(p_i\),其目标位置为 \(p_i\),假设其从 \(i\) 走到 \(p_i\),那么对于后面的每个要往前走的元素,必然两者会进行一次交换,于是往前走的元素的数量不能比 \(p_i-i\) 多。
换而言之,在他右边,比他小的元素不能多于 \(p_i-i\),另一种则是在他左边,比他大的元素不能多于 \(i-p_i\)
接着挖掘性质,发现对于 \(i\),假设他要往右走,那么左边不能有比他大的元素,假设他要往左走,那么右边不能有比他小的元素。
手玩后发现这个条件涵盖了之前的条件,而且感性上理解觉得他非常的是一个充分必要条件。
但是这样不好做,考虑找一个等价条件,注意到假设 \(p_i\) 要往右走,那么左边不存在比他大的,对于其右边一个比他小的元素,假设其往右走,那么这个元素比他大,非法,假设往左走,那么其右边不存在比他小的元素,所以逆序序列长度至多为 \(2\)
另一类同理,于是只需要统计逆序序列长度至多为 \(2\),字典序大于 \(q\) 的序列数。
考虑设 \(f_{i,j,0/1}\) 表示到位置 \(i\),最大值为 \(j\),当前字典序大于 \(q\) 还是等于 \(q\) 的方案数,转移的话有两种:填入的 \(x\) 大于 \(j\),另一种是小于,但是由于逆序序列长度不能超过 \(2\),所以比他小的元素不能存在逆序对,所以必然依次填入,所以序列确定了。
根据 0/1 进行讨论,复杂度 \(\mathcal O(n^3)\),可以获得 \(\rm 64pts\) /baojin
通过前缀优化可以做到 \(\mathcal O(n^2)\),可以获得 \(\rm 80pts\) 的高分 /jk
接下来枚举一个前缀,同时强制令 \(p_{1..i-1}=q_{1...i-1}\),且这个前缀目前合法,同时我们令 \(p_i>q_i\),此时将这些数剔除,问题变成剩余 \(m\) 个数,开头存在一个最大值 \(x\),当前数需要大于 \(q_i\),求不存在长度大于 \(2\) 的下降序列的方案数。
大于 \(q_i\) 的条件可以进行容斥,先统计满足前缀相同的方案数,然后减去小于等于 \(q_i\) 的方案数,如果 \(q_i>x\),那么暴力枚举,否则小于等于对应的数是唯一的,即 \(\rm mex\),不难发现总枚举量是 \(\mathcal O(n+\sum (\textrm{mx}_i-\textrm{mx}_{i-1}))\),即 \(\mathcal O(n)\)
考虑固定了一个前缀,可以把这些数拎出去,然后对于剩余数只关乎前缀最大值,将其作为开头,同时按照相对大小关系进行排序,不难发现问题变成了求 \(1\sim m\) 的排列中,开头固定为 \(x\),且合法的方案数。
考虑通过 Dp 统计,设 \(f_{i,j}\) 表示到位置 \(i\),最大值为 \(j\) 的方案数,转移为 \(f_{i,j}=\sum f_{i-1,k}[k\le j]\),转移的另一个前提是 \(j\ge i\)
构造直线 \(y=x-1\),不难发现问题所求即为从 \((0,x)\) 出发,且不经过此直线,到达 \((m,m)\) 的方案数。
对称,答案即为从 \((0,x)\) 出发和从 \((x+1,-1)\) 出发到达 \((m,m)\) 的方案数之差,即 \(\binom{2m-x}{m}-\binom{2m-x}{m+1}\)
于是我们只需要预处理 \(x\) 即可,\(m\) 显然就是 \(n-i\),而 \(x\) 则是对于位置 \(i\),后面没有出现过的元素比他小的元素个数\(+1\),统计一下前面比他小的元素个数即可,树状数组维护就 ok 了,复杂度 \(\mathcal O(n\log n)\)