[JOI 2021 Final] 地牢 3 题解
做法学习自 日语酱 的题解 /hs /bx。
本文旨在讲述我个人看完题解对此题做法的理解,可以视作对日语酱题解的注解(?。
本人很菜,很可能出错,请谅解 qwq。
首先,对样例进行模拟,得到一个贪心策略:当我们在第 \(i\) 层,找第 \(i\) 层后第一个 \(b\) 值小于 \(i\) 的楼层 \(p\),若 \(\mathrm{dis}(i,p)\le u\),就在第 \(i\) 层买恰好够走到第 \(p\) 层的能量,反之买满。正确性不难证明。
考虑如何实现这个贪心过程。我们发现,每次找 \(i\) 后更小值的过程很适合用单调栈配合实现。
具体地,固定终点 \(t\),倒序扫描 \(s\sim t\) 中的点,维护一个单调递增的单调栈。这样就可以快速执行我们的上述策略。
但有一个问题,当 \(i\) 和栈顶元素比较,将栈顶元素弹出时,\(i\) 可能会影响到栈顶元素的决策。我们需要计算 \(i\) 造成的影响。
记 \(i\) 到栈顶元素的距离为 \(L\)(显然,若有答案,则 \(L\le u\),在一开始判掉不合法的情况即可),到栈顶第二个元素的距离为 \(L'\),考虑分类讨论:
- \(L'\le u\),那么显然栈顶元素就是不必要的,减去的贡献长度为 \(L'-L\)。
- \(L'\gt u\),此时 \(i\) 处的决策显然是买满,走到栈顶元素的时候会余下 \(u-L\) 的能量,那么栈顶元素处买的能量显然会减去 \(u-L\)。
综上,发现 \(i\) 会对栈顶元素产生 \(\min(L',u)-L\) 的影响,直接撤销即可。
当 \(i\) 加入栈中,根据上文所述,会产生 \(\min(L,u)\) 的贡献。
但此时还是无法计算答案,因为 \(u\) 不是固定的。
仔细观察会发现,\(\min(L',u)-L\) 这个式子很有规律,将其视作 \(f(u)\),当 \(u\ge L'\) 的时候,这个式子是恒定的一条直线,当 \(u\lt L'\) 时,\(f(u)\) 呈一次函数状。
推广一下,考虑在一次操作里维护所有 \(f(u)\),假设维护的区间为 \([l,r]\),增加的贡献为 \(k\),则 \([l,r]\) 间元素的斜率会增大 \(k\),截距会减小 \(k\times (l-1)\)。对于 \((r,+\infty]\),斜率不会变化,而截距会增大 \(k\times (r-l+1)\)。用两个树状数组分别维护斜率和截距即可。
最后限制我们的只有答案的具体计算,因为询问的区间是变化的。
定义 \(F(s,t)\) 表示 \(s\to t\) 的答案,考虑按上述方法扫描线离线计算 \(F(i,n+1)\),对于每组询问 \((s,t,u)\),找出距离 \(t\) 不超过 \(u\) 的权值最小的点 \(m\),则答案为 \(F(s,n+1)-F(m,n+1)+\mathrm{dis}(m,t)\times b_m\)。
显然 \(s\to n+1\) 和 \(m\to n+1\) 的路径上,\(m\) 处一定会购买能量,而两处的决策是一样的,都是买满,所以恰好删去的 \(m\) 之后的贡献,并且 \(s\to m\) 路径上剩余的能量也会被利用上。可以画个图理解。
代码就不放了,太丑了 qwq。日语酱码风好看 /qq。