【树上的分治】poj1741

本文介绍了一种解决特定树形数据结构问题的方法,即通过分治算法统计距离不超过k的点对个数。文章详细阐述了算法原理,并提供了一个具体的实现案例。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

树是一种优美的数据结构(嗯嗯,这句话看过百遍了)。

 

这道题目的描述很清晰,给你一颗N个点(N<10000)有边权的无根树,要你统计满足距离不超过k的点对个数;

 

因为有多组数据的存在,所以平方的算法是不行的,便向NlogN靠近(貌似用什么NB数据结构可以O(N)?天啊。。)。

仔细分析了一下,其实是看了论文,对于每个满足条件的点对,他们之间有一条路径,对于每一个点,要么在这个路径上,要么在路径之外,这就让我们想到了使用分治算法:

      对于每一颗树,我们找到最优的这样一个根,使得以他儿子为根的子树中大小最大的最小。这样选跟是有意义的,可以使得递归分下去的层数最少,这样很容易证明分出的层数是小于等于logN层的(最坏情况一条链)。

      我们找到这样的根了,然后只要统计经过他的路径的条数就可以了,条件就是dep(i)+dep(j)<=k (i和j属于不同的子树)—> dep(i)<=k-dep(j),我是利用treap统计的,好像可以O(N)的线性扫描,无解。

      自己做完后,在递归到每颗子树就可以了。因为一共有logN层,每层要NlogN的统计,所以复杂度是 N log2N 的,速度很快,300ms。

 

代码自我感觉良好:

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值