three(长链剖分)

版权声明:本文为博主原创文章,未经博主允许必须转载。 https://blog.csdn.net/qq_35950004/article/details/85946804

给出一棵 n 个点的无根树,请在这棵树上选三个互不相同的节点,使得这个三个节点两两之间距离相等,输出方案数即可。n<=100000

这个题做法很多,但是 O ( n ) O(n) 长链剖分。。。。。。
请先自行百度。
因为长链剖分要节约内存,不能保存每个点的DP数组,那么我们得用完重儿子的DP数组之后就得继承和修改,不能再调回去。
有一个直观的想法就是枚举距离3个点都相等的点,这样如果3个点都在子树中固然好算(通过长链剖分求x子树内深度为h的点的数量 f [ x ] [ h ] f[x][h] ),可是如果要计算2个点在子树中还有一个点在上面的话就翻车了,毕竟计算在上面的点的时候,你只能从上往下计算,这样不仅和我们从下往上的 f ( x ) f(x) 的计算顺序相反,并且你算的时候还得借助 f ( x ) f(x)

正确的思路是枚举一定在最上面的点,即三个点的lca。
然后问题分为求在x子树内含有两个深度相同的节点且需求第3个点离x距离为k的方案数 h [ x ] [ k ] h[x][k] 和一个节点深度为k的 f [ x ] [ k ] f[x][k]
都可以长链剖分从下往上递推,最后就拿h[x][k]和f[x][k]合并就行了。

因为每个轻儿子的长链都只会被父亲计算一次,总复杂度是 O ( n ) O(n)
但是暴力加剪枝听说比这跑的更快

猜你喜欢

转载自blog.csdn.net/qq_35950004/article/details/85946804