P5853 [USACO19DEC]Tree Depth P

题面

对于每个 \(i\in[1,n]\),计数 \(i\) 在所有逆序对数为 \(m\)\(1\sim n\) 排列的小根笛卡尔树中的深度之和。

数据范围:\(n\le 300,m\le \frac{n(n-1)}{2}\)

题解

首先, \(i\) 的深度之和可以转化为对于 \(x\in[1,n]\)\(x\)\(i\) 祖先的方案数之和,也就是当 \(a_x\)\(a_{\min(x,i)}\sim a_{\max(x,i)}\) 中的最小值的方案数。

这看起来很神秘,尤其是还有一个逆序对数为 \(m\) 的限制。

于是我们从逆序对数是 \(m\) 的角度考虑。

一般我们考虑逆序对是从小到大把值插入到当前序列的哪个位置,但还可以这样考虑:

我们从左到右考虑这个位置加入的数和前面的数的大小关系,并产生相应的逆序对的贡献。

而且,我们不仅可以从左到右考虑插入,我们也可以从右往左,甚至可以一会从后插入,一会从前插入。

这样的化,我们发现上面的条件就很好满足了:

  • \(x<i\) ,我们就可以先从 \(i\) 扫到 \(x+1\) ,然后再加入 \(x\) ,因为此时 \(a_x\) 要是最小值,所以 \(a_x\) 此时只能产生 \(0\) 的逆序对数,其他的数的贡献方式都保持不变。
  • \(x>i\) ,类似的,我们先从 \(i\) 扫到 \(x-1\) ,然后再加入 \(x\) ,此时 \(a_x\) 此时只能产生 \(x-i\) 的逆序对数,其他的数的贡献方式都保持不变。

所以暴力就是枚举 \(i,x\) ,然后跑一遍dp,设 \(f_{i,j}\) 为已经插入 \(i\) 个数了,当前逆序对数是 \(j\) ,用前缀和优化可以得到单次 \(O(n^3)\) 的,所以总复杂度是 \(O(n^2\cdot n^3)\) 的。

但是我们发现对于 \(i-x\) 相同的一组,产生的贡献都是相同的。更进一步想,发现如果 \(i-x=x-i\),dp跑出来的结果也是相同的,唯一的不同就是 \(x>i\) 的那一组求的是 \(f_{n,m-x+i}\),所以我们可以只枚举 \(|i-x|\) ,然后跑dp,这样就是 \(O(n^4)\) 的。

我们发现每次都暴力dp太蠢了,我们可以考虑仿照背包撤销物品的方法,在这里考虑撤销一个转移。

发现对于 \(t=i-x\) ,它带来的转移是 \(f'_{i}=\sum_{j=i-t+1}^if_i\) ,那么我们就可以得到 \(f_i=f'_i-\sum_{j=i-t+1}^{i-1} f_i\) ,这样就可以用前缀和优化实现单词撤回 \(O(n^2)\) 的复杂度,所以整个题就是 \(O(n^3)\) 的了。

启发

  • 排列逆序对的求解方式可以很多样!!
  • 对于一些简单dp,是可以用较低复杂度去撤回的!!
posted @ 2022-08-02 10:47  qwq_123  阅读(64)  评论(0编辑  收藏  举报