【树上的分治】poj1741

来源:互联网 发布:linux 添加www用户组 编辑:程序博客网 时间:2024/04/24 23:06

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

 

这道题目的描述很清晰,给你一颗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。

 

代码自我感觉良好: