传送门
题目要求求出符合以下条件的树上点对个数:
1.两点间不能是祖先和子孙的关系
2.x点和y点的权值相加为2倍的他们的lca的权值
3.x点和y点间的距离小于等于给定的k
对于第一个条件,我们使用dsu on tree,每次枚举一个点,计算他为lca的答案即可。注意计算贡献的时候,要先计算一个子树的贡献,再将这个子树上的值加到我们使用的线段树上去,因为这样计算的才是其中一个点在一棵子树上,另一个点在另一颗子树上的答案,这样他们的路径是经过当前枚举的lca的。
对于第二个条件,我们使用动态开点线段树,对每一个权值开一棵线段树,这样可以控制“权值恰好等于”这个精确条件。由于空间可能不够所以使用动态开点。
对于第三个条件,我们在每个权值的线段树上,维护的是每个深度有几个节点,因此使用的是权值线段树,这样可以控制“距离小于等于”这个范围条件。两点间的距离是dep[x] + dep[y] - 2 * dep[lca],我们假设题意中符合条件的点的权值为val,深度要求小于等于k,那么我们就直接在rt[val]这颗线段树上查询0~k的值的个数有几个就行了。
于是这题就算完了,注意由于是点对,所以答案需要X2
#include
#include
#include
#include
#include
#include