NOI2018 D1T2 冒泡排序
求有多少个排列 (p),满足字典序严格大于 (q),且冒泡排序的交换次数到达下界。
(nle 6 imes 10^5)
( m 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)),可以获得 ( m 64pts) /baojin
通过前缀优化可以做到 (mathcal O(n^2)),可以获得 ( m 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),那么暴力枚举,否则小于等于对应的数是唯一的,即 ( m mex),不难发现总枚举量是 (mathcal O(n+sum ( extrm{mx}_i- extrm{mx}_{i-1}))),即 (mathcal O(n))
考虑固定了一个前缀,可以把这些数拎出去,然后对于剩余数只关乎前缀最大值,将其作为开头,同时按照相对大小关系进行排序,不难发现问题变成了求 (1sim m) 的排列中,开头固定为 (x),且合法的方案数。
考虑通过 Dp 统计,设 (f_{i,j}) 表示到位置 (i),最大值为 (j) 的方案数,转移为 (f_{i,j}=sum f_{i-1,k}[kle j]),转移的另一个前提是 (jge i)
构造直线 (y=x-1),不难发现问题所求即为从 ((0,x)) 出发,且不经过此直线,到达 ((m,m)) 的方案数。
对称,答案即为从 ((0,x)) 出发和从 ((x+1,-1)) 出发到达 ((m,m)) 的方案数之差,即 (inom{2m-x}{m}-inom{2m-x}{m+1})
于是我们只需要预处理 (x) 即可,(m) 显然就是 (n-i),而 (x) 则是对于位置 (i),后面没有出现过的元素比他小的元素个数(+1),统计一下前面比他小的元素个数即可,树状数组维护就 ok 了,复杂度 (mathcal O(nlog n))