Introduction
This is an alternative to j_random_hacker's solution, or more precisely, an alternative to his/her solution to the subproblem:
Given the ordered list of edge weights $x_1,\ldots,x_m$ encountered while traversing down a particular heavy path, we want to preprocess this list to enable us to be able to later efficiently answer queries of the form "How many of the first $r$ elements are less than $k$?"
j_random_hacker uses the data structure of Fenwick tree of sorted lists, which results in a solution with
- overall $O(n\log^3 n)$ preprocessing time for all heavy paths,
- overall $O(n\log n)$ space for all heavy paths, and
- $O(\log^2 n)$ query time for the subproblem, hence $O(\log^3 n)$ query time for the primary problem.
In contrast, my alternative gives a solution with
- overall $O(n\sqrt{n})$ preprocessing time for all heavy paths,
- overall $O(n\sqrt{n})$ space for all heavy paths, and
- $O(1)$ query time for the subproblem, hence $O(\log n)$ query time for the primary problem.
How to preprocess each heavy path?
In the very first, before we turn to those heavy paths, we sort all edges according to their weights from small to large. Say the result is $e_1,\ldots,e_{n-1}$ with weights $w_1,\ldots,w_{n-1}$. We label edge $e_i$ by $i$ for future use. Denote $I_1=(-\infty,w_1],I_2=(w_1,w_2],\ldots,I_n=(w_{n-1},+\infty)$.
Now let's focus on the subproblem mentioned above. We divide $x_1,\ldots,x_m$ into blocks of length $t=\lceil\sqrt{n}\rceil$: $\left[x_1,\ldots,x_t\right],\left[x_{t+1},\ldots,x_{2t}\right],\ldots$ We build two tables $T_1, T_2$ where $T_1(p,q,r)$ represents how many of the first $r$ elements in the $q$th block are less than $k$ if $k\in I_p$, and $T_2(p,q)$ represents how many of the elements in the first $q$ blocks are less than $k$ if $k\in I_p$.
Now if we have these two tables, we can answer an query for each heavy path in $O(1)$ time. For example, for a query $(r,k)$, if $k\in I_5$ and $r=3t+2$, then the answer is $T_1(5,4,2)+T_2(5,3)$.
Note it takes $O(\log n)$ time to find $p$ such that $k\in I_p$. Since we need to do this search only once for each query of the primary problem, it does not increase the query time.
How to build these tables?
Note $T_2(p,q)=\sum_{i=1}^q T_1(p,i,t)$, if we already have $T_1$, we can build $T_2$ in $O(nm/t)$ time and it takes $O(nm/t)$ space. Next we focus on how to build $T_1$.
Suppose the edge weights in the $q$th block are $w_{i_1},\ldots,w_{i_t}$ where $i_1<\cdots<i_t$ (recall that these edges are already labeled by $i_1,\ldots,i_t$). Then we have
\begin{align}
T_1(1,q,*)=T_1(2,q,*)=&\cdots=T_1(i_1,q,*),\\
T_1(i_1+1,q,*)=T_1(i_1+2,q,*)=&\cdots=T_1(i_2,q,*),\\
&\cdots\\
T_1(i_t+1,q,*)=T_1(i_t+2,q,*)=&\cdots=T_1(n,q,*),
\end{align}
where $T_1(p,q,*)$ represents the array $[T_1(p,q,1),\ldots,T_1(p,q,t)]$, and two arrays are equal if they are element-wise equal. This means we only need to compute and store $t$ arrays for $T_1(1, q, *),\ldots,T_1(n, q, *)$. So we can build $T_1$ in $O(t^2\cdot m/t)=O(mt)$ time, and it also takes $O(mt)$ space.
Note $t=\lceil\sqrt{n}\rceil$, the overall preprocessing time for all heavy paths are
$$
\sum_m O(m\sqrt{n})=O(n\sqrt{n}).
$$
So is the overall space used.