P6773 [NOI2020] 命运 题解
题意
给定一棵 \(n\)(\(n\le 5\times 10^5\))个节点的有根树和 \(m\)(\(m \le 5\times 10^5\))条返祖链。现在要求用黑白两种颜色给所有边染色,使得每条返祖链都有至少一条边是白色的。问染色方案数对 \(998244353\) 取模的结果。
题解
记返祖链的底端为其起点,顶端为其末端。
容易发现,从同一个节点出发的多条返祖链,只有末端最深的一个是有效的。我们给每个节点维护一个数组 \(w[u]\) 表示从该起点出发的所有返祖链中,末端的最大深度。若没有从该节点出发的返祖链,则 \(w[u]=0\)。
因为我们可以在根节点上方挂一条虚边,钦定这条虚边始终为白色,再从所有节点都向这个虚边上方连一条返祖链,就可以将有、无剩余返祖链的情况简单的统一。
考虑一种朴素的 dp
,设 \(dp_{u,j}\) 表示节点 \(u\) 的子树中,整个都在子树内的限制(返祖链)都被满足,而没有被满足的所有返祖链的末端节点中最深的一个深度为 \(j\),方案数是多少。(若所有都被满足,则 \(j=0\))
容易写出状态转移方程:
\[
dp'_{u,j}=dp_{u,j}\times (\sum_{k=0}^{j}{dp_{v,k}}+\sum_{k=0}^{dep_u}{dp_{v,k}})+(\sum_{k=0}^{j-1}{dp_{u,k}})\times dp_{v,j}
\]
其中,第 \(1\)、\(2\) 项表示新增的子树 \(v\) 没有改变最深的末端深度;第 \(3\) 项表示 \(v\) 产生了一条末端更深的未处理的返祖链。
这种式子可以直接使用线段树合并优化。
- 对于 \(\sum\limits_{k=0}^{dep_u}{dp_{v,k}}\) 的常数,可以在调用
merge()
之前对 \(v\) 的线段树调用query()
得到,记为 \(c\); - 对于 \(dp_{v,k}\) 和 \(dp_{u,k}\) 的前缀和,因为线段树合并的递归顺序是一种前序遍历的
dfs
序,可以在dfs
的时候动态维护两个变量 \(sum_1\) 和 \(sum_2\),分别记录两个前缀和。
调用处:
完整代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 |
|