编了一个奇怪的做法,看起来好像都不太一样。 考虑单调栈找到每个位置后第一个比其小的点,然后连边(以那个点为父亲)可以连出一棵森林。注意到区间询问其实只需要关心这个点祖先链上的一段点。 那么将询问离线,然后在树上线段树合并。在讨论节点 $u$ 到其父亲的贡献时,在 $[u,\mathrm{fa}_u]$ 这一段区间中,之前的区

编了一个奇怪的做法,看起来好像都不太一样。

考虑单调栈找到每个位置后第一个比其小的点,然后连边(以那个点为父亲)可以连出一棵森林。注意到区间询问其实只需要关心这个点祖先链上的一段点。

那么将询问离线,然后在树上线段树合并。在讨论节点 \(u\) 到其父亲的贡献时,在 \([u,\mathrm{fa}_u]\) 这一段区间中,之前的区间买的票会超过 \(u\) 一些,然后就开始用 \(u\) 的票直到 \(\mathrm{fa_u}\)

超过 \(u\) 的长度和之前走的长度模 \(k\) 的余数有关,同时不同多出的长度用的 \(u\) 的票数只有两种,且在模 \(k\) 的余数区间上一定有一种是连续的。

那么将所有的位置按照模 \(k\) 的结果重标号后建立线段树,每次只需要区间修改就行。询问是单点询问,总时间复杂度 \(O(n+m)\log n\)

代码:Submission #133112330 - Codeforces