思路:
我们可以对于每个 \(i\) 找到它能跳到的最远的点和近来的点,倍增求一下 \(k\) 级祖先即可,令 \([l_i,r_i]\) 新表示 \(i\) 能跳到其祖先中深度在 \([l_i,r_i]\) 内的点;同时令 \(lim_i = d_i - h_i-1\) 表示 \(i\) 至少要跳到 \(lim_i\) 的深度。
考虑动态规划算法,令 \(dp_i\) 表示从 \(i\) 出发到山顶的合法登山序列个数。
那么相当于先从 \(i\) 滑落到 \(j\),然后再从 \(j\) 冲刺到 \(k\),再加上 \(dp_k\) 的方案数。
则状态转移方程为:
\[dp_i = \sum_{j 在 i 子树内} \sum_{k 为 i 的祖先} (d_k \in [l_j,\min(W(i,j),r_j)]) dp_k\]
其中 \(W(i,j)\) 表示 \(i \to j\) 路径上 \(lim_k\) 的最小值,由于每次冲刺到达的深度必须小于所有颠末的点的 \(lim_k\)。
质朴实现是 \(O(N^3)\) 的,考虑优化;注意到 \(k\) 是 \(i\) 的祖先中一段深度连续的点,则我们可以做一个深度的 \(dp_i\) 的前缀和,差分即可,时间复杂度优化至 \(O(N^2)\),可以得到 25pts。
$O(N^2)$ Code: [code]namespace Sub1{ ll L,R,x,a,b; ll s[N],dp[N],dep[N]; void dfs1(ll u){ for(auto v:E){ if(v==fa) continue; dep[v]=dep+1; dfs1(v); } } ll get(ll l,ll r){ if(!l) return s[r]; return (s[r]-s[l-1]+mod)%mod; } void dfs3(ll u,ll Min,ll from){ L=l,R=min(r,Min); if(L1; build(k |