【杂记】有上限的树上背包问题的时间复杂度证明

发布时间 2024-01-08 19:35:36作者: rizynvu

结论:若树上背包的上限为 \(k(k\le n)\),时间复杂度为 \(O(nk)\)

参考实现:

dfs(u) {
    sz[u] = 1; init(f[u]);
    for (v : son[u]) {
        dfs(v);
        for (i = 0; i <= k and i <= sz[u])
            for (j = 0; i + j <= k and j <= sz[v])
                upd(f[u][i + j], f[u][i], f[v][j]);
        sz[u] += sz[v];
    }
}

证明(参考了这一篇):

考虑令 \(sz_u\le k\) 的子树 \(u\) 为小子树,否则为大子树。
\(fa_u\) 为大子树而 \(u\) 为小子树的子树 \(u\) 为极小大子树。
\(v\in son_u\) 均为小子树而 \(u\) 为大子树的 \(u\) 为极大小子树。

性质 \(1\)
令极小大子树的子树的根分别为 \(R_{1\sim c}\)
那能保证对于 \(1\le i < j\le c\)\(R_i\)\(R_j\) 子树内的点不重,因为其肯定不为包含关系且两点在同一颗在树上。
所以 \(\sum\limits_{i = 1}^m sz_{R_i}\le n\),又因是大子树所以 \(sz_{R_i} > k\),所以 \(c < \lfloor\frac{n}{k}\rfloor\)

性质 \(2\)
令极大小子树的子树的根分别为 \(U_{1\sim m}\)
那能保证对于 \(1\le i < j\le m\)\(U_i\)\(U_j\) 子树内的点不重,同上。
所以有 \(\sum\limits_{i = 1}^m sz_{U_i} \le n\)

首先考虑小子树内部的合并。
考虑把这些都归到极大小子树 \(u\) 上。
\(A, B\) 两部分合并,那对应的时间复杂度为 \(O(sz_A\times sz_B)\),那考虑把这个贡献拆为 \(A\) 子树中的点 \(u\)\(B\) 子树中的点 \(v\) 在这里的合并。
那么每两个点都只会产生一次贡献,所以 \(u\) 子树产生的贡献是 \(O(sz_u^2)\)
那么时间复杂度为 \(O(\sum\limits_{i = 1}^m sz_{U_i}^2)\)
因为对于 \(x > y, c > 0\)\((x + c)^2 + (y - c)^2> x^2 + y^2\),且根据性质 \(2\)\(\sum\limits_{i = 1}^m sz_{U_i} \le n\)
所以 \(\sum\limits_{i = 1}^m sz_{U_i}^2\le k^2\times \frac{n}{k} = nk\),所以这部分时间复杂度为 \(O(nk)\)

考虑小子树与大子树的合并。
发现这肯定只会发生在极大小子树 \(u\) 和其父亲 \(fa_u\) 上。
那么这次合并时间复杂度为 \(O(k\times sz_u)\)
总的时间复杂度就为 \(O(k\times \sum\limits_{i = 1}^m sz_{U_i})\)
根据性质 \(2\)\(\sum\limits_{i = 1}^m sz_{U_i} \le n\),所以时间复杂度为 \(O(nk)\)

考虑大子树和大子树的合并。
那么每次合并的复杂度就是 \(O(k^2)\) 的。
发现本质上还是极小大子树的合并,所以合并次数 \(=\) 极小大子树数量 \(-1\)
又根据性质 \(1\)\(c < \lfloor\frac{n}{k}\rfloor\),所以总时间复杂度 \(O(\frac{n}{k}\times k^2)\)\(O(nk)\)

综上,时间复杂度为 \(O(nk)\)