「NOI2024」登山
这是一个补题时自己胡出来的逆天大常数劣复杂度做法,洛谷上最慢点 1.92s。
显然每次冲刺到的点深度都是递减的,并且下一次冲刺的深度限制只与上一次冲刺到的点以及上一次到现在的休息点相关(这些点的 \(d-h\) 限制以及出发点的 \([l,r]\) 限制)。我们考虑令 \(f_i\) 表示从 \(i\) 出发到 \(1\) 的方案数,那么枚举 \(i\) 子树中的一个节点 \(j\) ,那么我们将 \(f_j\) 加上 \(f_i\times g_{i,j}\),其中 \(g_{i,j}\) 表示 \(j\) 子树内有多少节点,其到 \(j\) 路径上的 \(d-h\) 最小值大于 \(d_i\),并且 \(d_i\) 在其能跳到的区间内。这样可以暴力做到 \(\mathcal O(n^2)\)。
考虑优化,我们按照深度从小到大枚举,假如说当前枚举到了深度 \(t\),我们对于每个 \(i\) 维护 \(g_{x,i}\),其中 \(x\) 是 \(i\) 的深度为 \(t\) 的祖先。容易发现,我们会不断让一些点的 \(d-h\le t\),这意味着这些节点不能够成为选中点到 \(j\) 路径上的点,我们称其为被涂黑。假如我们钦定一个出发点,那么从它出发的一段极长白色前缀祖先的 \(f\) 值会增加 \(f_x\)。也即是 \(g_{x,i}\) 表示 \(i\) 的子树中,\(i\) 所在白色连通块中满足 \(d_x\in[d_j-r_j,d_j-l_j]\) 的 \(j\) 数量(若 \(i\) 为黑色则是 \(0\))。随着深度的推进,我们可能会进行一下两种操作:
-
涂黑一个点 \(x\):容易发现,令 \(\text{find}(x)\) 为 \(x\) 的最浅祖先,使得其到 \(x\) 路径全白,则 \(x\) 到 \(\text{find}(x)\) 的 \(g\) 减去 \(x\) 的 \(g\),再标记 \(x\) 为黑色。
-
使一个点 \(x\) 满足/不满足区间限制:若 \(x\) 已经被涂黑,则跳过。否则将 \(x\) 到 \(\text{find}(x)\) 的 \(g\) 全部加上/减去 \(1\) 即可。
然后再枚举这一层的所有点,从其出发有 \(k\) 的转移量,就是将子树内的 \(f_i\) 值都加上 \(k\times g_{x,i}\)。这些操作都可以线段树维护,具体信息就是区间 \(\sum A_i\times B_i\) 以及区间 \(\sum B_i\),操作就是每次 \(A\) 或者 \(B\) 的区间加,用树链剖分加线段树即可做到 \(\mathcal O(n\log^2n)\) 的时间复杂度。细节很少,比较好写。但是其实是比较没用的乐子做法。