2019hdu多校六 Ridiculous Netizens(点分治)

大概题意是: 给你一颗无根树,每一个结点有点权, 有多少颗子树的结点乘积不超过m?子树的定义是树上的连通块。

首先我们考虑另一个问题,假设给你一颗有根树,所以包含根的子树有多少种满足乘积不超过m?

考虑树形dp的做法,定义dp[i][j]是在i被选取后 这颗子树中乘积为j的子树方案数,这样每次将两颗子树合并的复杂度是m*m的。但实际上子树大小限制了状态数不会那么多,所以每次计算一个点的贡献的复杂度是 o(m)的。

这里题解有一个很巧妙的求法,因为如果一个点被选取,那么他的父亲一定被选取。如果一个点不被选取,那么它子树中的所有点也不会被选取。所以当我们从fa->u时,dp[fa]已经包含了u不被选取的情况(因为u还没有被搜索,没有任何节点统计了贡献)。那么我们只需要统计u被选取的情况,因为u被选取了,那么fa一定也被选取了,所以u可以继承fa的信息,然后继续递归即可。

但是这样dfs一次的复杂度是n*m的,还是有点吃不消。注意题目中要求的是乘积。我们可以考虑剩余的子树大小,比如当前有两颗乘积为m,m-1的子树,那么他们都只能在添加大小为1的子树,所以状态可以合并。其实就是一个整除分块。所以dp[i][j]表示i点在选取后还能添加大小为j的子树的方案数,这样状态数只有^{\sqrt{m}}。复杂度是o(n*

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值