P7897 [Ynoi2006] spxmcq
并不太难的一个 Ynoi。
首先考虑一个暴力 dp。$f_u$ 表示 $u$ 结点的答案。则有:
$$f_u=a_u+x+\sum_{u\to v}\max(f_v, 0)$$
后面的东西不太好处理,我们注意到 $0$ 是无效转移,于是我们维护一个新的结构,在 $f_v\ge 0$ 时才将 $u\to v$ 这条边连上。容易发现这是一个森林。在这个森林中,一个点的答案即为
$$f_u=a_u+x+\sum_{u\to v}f_v$$
展开发现 $f_u$ 本质为 $siz_u\cdot x+tot_u$,其中 $siz_u,tot_u$ 表示森林中的 $u$ 的子树中结点个数与权值之和。看起来十分好维护了。
而随着 $x$ 的增加,$f_u$ 显然不减,于是我们得到的森林的边集是有包含关系的。这启发我们去离线询问,按 $x$ 升序排序,然后去动态地维护森林。每条边只会更改一次状态(从“不出现在森林中”变成“出现在森林中”),所以复杂度是正确的。
什么边会被加入到森林里呢?此时有 $siz_u\cdot x+tot_u\ge 0$,于是 $x\ge \left\lceil-\dfrac{tot_u}{siz_u}\right\rceil$,也就是说森林中一个根节点在原树中通往父亲的那条边可以被连上,当且仅当当前询问的 $x$ 不小于 $\left\lceil-\dfrac{tot_u}{siz_u}\right\rceil$。如何快速找出这样的边呢,使用 multiset/set 维护即可。
那么,现在问题转化为了:
- 在森林中连边
- 维护森林中每个点的 $siz_u$ 和 $tot_u$
考虑连上一条边对所要维护信息的影响。记这条边深度较大者为 $u$,其父亲也就是这条边的另一个端点为 $fa_u$,其父亲所在联通块的根为 $p$。而更新了 $siz$ 和 $tot$ 的结点,恰好是 $fa_u$ 到 $p$ 的路径上的点,并且是简单的链加操作。使用树状数组维护 dfn 序树上差分即可。找联通块根使用并查集实现。
此题卡常,AC 记录最大点 2.98s,不保证任何时候均可使用此代码通过本题。
Code。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 单线程的Redis速度为什么快?
· SQL Server 2025 AI相关能力初探
· AI编程工具终极对决:字节Trae VS Cursor,谁才是开发者新宠?
· 展开说说关于C#中ORM框架的用法!