【题目】NowCoder-1100B 乃爱与城市拥挤程度

题目大意

给出一棵 n n n个结点的树以及一个常数 k k k,对于树中的每个结点 v v v,求出:

  1. 到点 v v v的距离不超过 k k k的点的个数。
  2. 若点 x x x距离点 v v v不超过 k k k,则 v , x v,x v,x路径上的所有点的权值加 1 1 1。求距离 v v v不超过 k k k的点的权值的乘积。答案对 1 0 9 + 7 10^9+7 109+7取模。

n ⩽ 1 0 5 n\leqslant 10^5 n105 k ⩽ 10 k\leqslant 10 k10


思路

应该能看出是树形DP。
首先要考虑到贡献的计算。在询问某个点 u u u的时候,对于 u u u本身,其子树内外的贡献都要计算;对于 u u u下方的点,只计算其子树内的贡献;对于 u u u子树外的点,只计算其子树外的贡献。因此DP状态分子树内外两种情况讨论。

讨论的时候用 ( u , v ) (u,v) (u,v)表示一条父子边,其中 u u u是父亲。

先解决第一个问题。

f [ u ] [ i ] [ 1 ] f[u][i][1] f[u][i][1]表示点 u u u子树内距离 u u u不超过 i i i的点的个数(包括点 u u u本身), f [ u ] [ i ] [ 0 ] f[u][i][0] f[u][i][0]表示点 u u u子树外距离 u u u不超过 i i i的点的个数(不包括点 u u u本身)。
对于 f [ u ] [ i ] [ 1 ] f[u][i][1] f[u][i][1],既然到 u u u的距离为 i i i,那么到 u u u的某个儿子 v v v的距离一定是 i − 1 i-1 i1,可以累计儿子的贡献,再加上 u u u本身,得到第一个方程:
f [ u ] [ i ] [ 1 ] = ( ∑ f [ v ] [ i − 1 ] [ 1 ] ) + 1 f[u][i][1]=\bigg(\sum f[v][i-1][1]\bigg)+1 f[u][i][1]=(f[v][i1][1])+1

对于 f [ v ] [ i ] [ 0 ] f[v][i][0] f[v][i][0],子树外的点到父亲 u u u的距离也一定是 i − 1 i-1 i1,并且既可以来自 u u u的子树外,也可以来自 u u u的其它儿子。既然是其它儿子,就要减去 u u u这棵子树的贡献,得到第二个方程:
f [ v ] [ i ] [ 0 ] = f [ u ] [ i − 1 ] [ 0 ] + f [ u ] [ i − 1 ] [ 1 ] − f [ v ] [ i − 2 ] [ 1 ] f[v][i][0]=f[u][i-1][0]+f[u][i-1][1]-f[v][i-2][1] f[v][i][0]=f[u][i1][0]+f[u][i1][1]f[v][i2][1]

最终答案为每个结点子树内外的贡献之和,由于结点本身的贡献只在子树内被计算,不需要去重。不难发现这个答案就是第二个问题中的点权。
a n s 1 [ u ] = f [ u ] [ k ] [ 0 ] + f [ u ] [ k ] [ 1 ] ans_1[u]=f[u][k][0]+f[u][k][1] ans1[u]=f[u][k][0]+f[u][k][1]

然后是第二个问题。

g [ u ] [ i ] [ 1 ] g[u][i][1] g[u][i][1]表示点 u u u子树内距离 u u u不超过 i i i的点(包括点 u u u本身)在到达点 u u u的路径上对经过的点的权值加 1 1 1后,点 u u u子树内距离 u u u不超过 i i i的点的权值的乘积。 g [ u ] [ i ] [ 0 ] g[u][i][0] g[u][i][0]的含义同理,就不费口舌叙述了。

对于 g [ u ] [ i ] [ 1 ] g[u][i][1] g[u][i][1],即点 u u u子树内的点,同样可以累计儿子的贡献,再乘上点 u u u本身的权值。点 u u u子树内能到达点 u u u的点一共有 f [ u ] [ i ] [ 1 ] f[u][i][1] f[u][i][1]个,每一个点都会对点 u u u的权值加 1 1 1,因此点 u u u的权值就为 f [ u ] [ i ] [ 1 ] f[u][i][1] f[u][i][1],得到第三个方程:
g [ u ] [ i ] [ 1 ] = ( ∏ g [ v ] [ i − 1 ] [ 1 ] ) ⋅ f [ u ] [ i ] [ 1 ] g[u][i][1]=\bigg(\prod g[v][i-1][1]\bigg)\cdot f[u][i][1] g[u][i][1]=(g[v][i1][1])f[u][i][1]

对于 g [ v ] [ i ] [ 0 ] g[v][i][0] g[v][i][0],即点 v v v子树外的点,同样可以先到父亲 u u u,累计 u u u的贡献,再除去 v v v这棵子树的贡献,得到第四个方程:
g [ v ] [ i ] [ 0 ] = g [ u ] [ i − 1 ] [ 0 ] ⋅ g [ u ] ] [ i − 1 ] [ 1 ] g [ v ] [ i − 2 ] [ 1 ] g[v][i][0]=\frac{g[u][i-1][0]\cdot g[u]][i-1][1]}{g[v][i-2][1]} g[v][i][0]=g[v][i2][1]g[u][i1][0]g[u]][i1][1]

如果你列出的方程是上面这个样子,你就完了。
第四个方程有非常严重的错误。我们试图用 g [ u ] [ i − 1 ] [ 0 ] ⋅ g [ u ] [ i − 1 ] [ 1 ] g[u][i-1][0]\cdot g[u][i-1][1] g[u][i1][0]g[u][i1][1]计算所有距离 u u u不超过 i − 1 i-1 i1的点到达点 u u u后产生的点权的乘积,显然子树内外的贡献都要计算。但此时点 u u u的点权被拆成了两部分:来自子树内的 f [ u ] [ i − 1 ] [ 1 ] f[u][i-1][1] f[u][i1][1]和来自子树外的 f [ u ] [ i − 1 ] [ 0 ] f[u][i-1][0] f[u][i1][0]。首先 g [ u ] [ i − 1 ] [ 0 ] g[u][i-1][0] g[u][i1][0]根本就不包含点 u u u来自子树外的贡献 f [ u ] [ i − 1 ] [ 0 ] f[u][i-1][0] f[u][i1][0];即使 g [ u ] [ i − 1 ] [ 0 ] g[u][i-1][0] g[u][i1][0]包含了 f [ u ] [ i − 1 ] [ 0 ] f[u][i-1][0] f[u][i1][0],上面的方程也是把点 u u u的两部分权值相乘,但是显然这两部分应该是相加的关系。(不清楚的可以手动模拟)
于是这个方程中点 u u u的权值是错误的。由于我们知道这个错误的权值是 f [ u ] [ i − 1 ] [ 1 ] f[u][i-1][1] f[u][i1][1],可以把这个错误的权值除掉,把正确的权值乘上去,注意仍然要减去点 v v v这棵子树的贡献。
g [ v ] [ i ] [ 0 ] = g [ u ] [ i − 1 ] [ 0 ] ⋅ g [ u ] ] [ i − 1 ] [ 1 ] g [ v ] [ i − 2 ] [ 1 ] ⋅ f [ u ] [ i − 1 ] [ 0 ] + f [ u ] [ i − 1 ] [ 1 ] − f [ v ] [ i − 2 ] [ 1 ] f [ u ] [ i − 1 ] [ 1 ] = g [ u ] [ i − 1 ] [ 0 ] ⋅ g [ u ] ] [ i − 1 ] [ 1 ] g [ v ] [ i − 2 ] [ 1 ] ⋅ f [ v ] [ i ] [ 0 ] f [ u ] [ i − 1 ] [ 1 ] \begin{aligned} g[v][i][0]&=\frac{g[u][i-1][0]\cdot g[u]][i-1][1]}{g[v][i-2][1]}\cdot\frac{f[u][i-1][0]+f[u][i-1][1]-f[v][i-2][1]}{f[u][i-1][1]}\\ &=\frac{g[u][i-1][0]\cdot g[u]][i-1][1]}{g[v][i-2][1]}\cdot\frac{f[v][i][0]}{f[u][i-1][1]} \end{aligned} g[v][i][0]=g[v][i2][1]g[u][i1][0]g[u]][i1][1]f[u][i1][1]f[u][i1][0]+f[u][i1][1]f[v][i2][1]=g[v][i2][1]g[u][i1][0]g[u]][i1][1]f[u][i1][1]f[v][i][0]

同理,最终统计答案的时候也不能直接把子树内外的贡献相乘了,还是需要先把错误的权值除掉,乘上正确的权值。
a n s 2 [ u ] = g [ u ] [ k ] [ 0 ] ⋅ g [ u ] [ k ] [ 1 ] ⋅ f [ u ] [ i − 1 ] [ 0 ] + f [ u ] [ i − 1 ] [ 1 ] f [ u ] [ i − 1 ] [ 1 ] ans_2[u]=g[u][k][0]\cdot g[u][k][1]\cdot\frac{f[u][i-1][0]+f[u][i-1][1]}{f[u][i-1][1]} ans2[u]=g[u][k][0]g[u][k][1]f[u][i1][1]f[u][i1][0]+f[u][i1][1]

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值