简单的树上问题

122 篇文章 0 订阅

题目

题目描述
给定一棵有 n n n 个节点的无根树,树上的每个点有一个非负点权。

定义一条路径的价值为路径上的点权和 − - 路径上的点权最大值。形式化地,设 v x v_x vx 为点 x x x 的权值,路径 X X X 的价值为 ∣ X ∣ |X| X ,则

∣ X ∣ = ∑ i ∈ X v i − max ⁡ i ∈ X v i |X|=\sum_{i\in X}v_i-\max_{i\in X}v_i X=iXviiXmaxvi

给定参数 P P P ,我们想知道,有多少不同的树上简单路径,满足它的价值恰好是 P P P 的倍数。

数据范围与约定
n ≤ 1 0 5 , P ≤ 1 0 7 n\le 10^5, P\le 10^7 n105,P107

思路

耿直的暴力

从每个点开始 b f s / d f s \tt{bfs/dfs} bfs/dfs 一次即可。复杂度 O ( n 2 ) \mathcal O(n^2) O(n2)

题外话:我打了倍增,成功地优化至 O ( n 2 log ⁡ n ) \mathcal O(n^2\log n) O(n2logn) 。另一个同学 w x k \tt wxk wxk 打了树剖,优化至 O ( n 2 log ⁡ 2 n ) \mathcal O(n^2\log^2n) O(n2log2n)

对于一条链

取链的中点 m m m ,只考虑经过 m m m 的路径。递归地计算不经过 m m m 的路径。

用两个指针,分别是从 m m m l l l 、从 m m m r r r ;用两个桶存储每个权值和出现的次数(模 P P P 意义下)。每次将最大值较小的指针移动一步。

总之,我们要求的就是——最大值在左边、最大值在右边这两种情况。在桶里直接找答案。

这是 O ( n log ⁡ n ) \mathcal O(n\log n) O(nlogn) 的。

推广到树上

每次只考虑当前这个子树的根作为 l c a lca lca

还是用桶,换成用堆来求子树内的点。总之,目的还是求最大值在某个子树内的情况。

可惜的是,我们会错误的计算——我们没有避免取了两个同子树内的点。于是我们对子树再做一次,减掉这些多了的。

虽然我们的树高不稳定,但是对于随机数据,能做到 O ( n log ⁡ 2 n ) \mathcal O(n\log^2 n) O(nlog2n)

加一点优化

套点分治即可。递归层数此时便稳定了,时间复杂度稳定在 O ( n log ⁡ 2 n ) \mathcal O(n\log^2 n) O(nlog2n)

题外话:原题解中这样写——“感觉地球人都知道怎么做”。看来我被剥夺了“球籍”

代码

原题解中这样写——“本套题中的代码量担当”。于是我放弃了。出题人的名称: v i s i t _ w o r l d \tt{visit\_world} visit_world

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值