第二类斯特林数 + 线段树优化 dp 转移.
USACO 怎么也有如此套路的题…
可以先将所有线段按照左端点从小到大排序,方便后续处理.
记一个非空集合 $T$ 的线段形成的连通块数目为 $c(T)$ ,则答案为 $\sum_T c(T)^k$ .
朴素的 dp
设 $dp(i,x,p)$ 表示考虑了前 $i$ 条线段,选了的线段右端点最大值为 $x$ ,有 $p$ 个连通块的方案数.
这样做状态数为 $O(n^3)$ ,不太可行.
幂次展开为组合数
注意到 $k$ 比较小,尝试将其展开为组合数的形式,
$$
\begin{aligned}
ans&=\sum_T c(T)^k \\
&=\sum_T\sum_{i=0}^k {k\brace i}\cdot i!\cdot \binom{c(T)}{i}\\
&=\sum_{i=0}^k{k\brace i}\cdot i!\cdot \sum_{T}\binom{c(T)}{i}
\end{aligned}
$$
当题目中要算 $c^k$ 的贡献, $c$ 大而 $k$ 小,尤其是 $c$ 是某种东西的数目时,可以尝试展开成组合数.
原来需要记录 $c$ 的大小,最后算贡献,现在就将贡献摊在每个 $c$ 增大的时候计算,只用记录 $k$ 的大小.
于是我们在状态中就不需要记录连通块数目,而是在新产生一个连通块时,考虑它是否被选.
设 $dp(i,x,p)$ 表示考虑了前 $i$ 条线段,选了的线段右端点最大值为 $x$ ,产生的连通块被选定了 $p$ 个的方案数.
状态数从 $O(n^3)$ 降到了 $O(n^2k)$ ,还需进一步优化.
线段树优化转移
考虑转移的形式,假定当前在考虑第 $i$ 条线段,其覆盖的区间为 $[l,r]$ .
若不选这条线段,则每个 $dp(i-1,x,p)$ 转移到 $dp(i,x,p)$ .
若选了这条线段,则根据 $x$ 的大小分情况讨论.
若 $x<l$ ,此时会产生新的一个连通块, $dp(i-1,x,p)$ 可以转移到 $dp(i,r,p)$ 和 $dp(i,r,p+1)$ .
若 $l\le x\le r$ , $dp(i-1,x,p)$ 可以转移到 $dp(i,r,p)$ .
若 $x>r$ , $dp(i-1,x,p)$ 可以转移到 $dp(i,x,p)$ .
不难发现,我们可以开 $k+1$ 棵线段树来维护这个 dp 数组,第 $p$ 棵线段树维护了当前所有的 $dp(i,x,p)$ .
时间复杂度 $O(nk\log n)$ .
1 | //%std |