考虑到 f 那部分一共只有 O(\log n) 项,而再 O(\log n) 时间内计算单点的 f 自然是简单的,于是这部分容易做到 O(n\log^2n)。现在考虑如何计算一条链上所有点的 g_{\cdot,d} 之和。
考虑差分成 1\to x 链上所有点的 g_{\cdot,d} 之和,我们注意到每个点的所有轻儿子的子树大小之和为O(n\log n),这允许我们从根开始往下 DFS,每次遇到一个点,就遍历他的所有轻儿子的子树内的所有点,并计算他对 g 的贡献。具体来说,我们动态地维护序列 G_i=\sum_{u\in\text{path}(1,x)}g_{u,i},每次新进入一个点 x 时,暴力扫他的轻儿子的子树内的每个点 v,并令 G_{\text{dis}(v,x)}\leftarrow G_{\text{dis}(v,x)}+1。则查询只需查询前缀和,使用树状数组维护即可,时间复杂度 O(n\log^2n)。
最后,由于实际距离 \le d 的点可能在子树外,我们还需要使用某些树分治算法进行一遍树上邻域数点。这部分也容易做到 O(n\log^2n) 以内。
最后的最后,我们实际上询问的并非祖先-后代链;设实际询问的是 x\to y 这条链,z=\text{LCA}(x,y),我们分别对 z\to x,z\to y 算出 z 子树内与这条链距离 \le d 的点数,那么多算的部分恰好就是 z 子树内与 z 距离 \le d 的点数,即 f_{z,d}。最后加上 z 子树外与 z 距离 \le d 的点数即可。