QOJ12023 代金券 题解

草啊,一个周做了一道题,真是高效的训练!

题意简述

假设你要连续 \(n\) 天在食堂吃饭,第 \(i\) 天饭的价格为 \(a_i\)。给定一个正整数 \(c\),现有一种代金券,如果你在某一天消费了 \(x\) 元,则你可以获得 \(\lfloor \frac{x}{c} \rfloor\) 张代金券,每张代金券的价值为 \(1\),即你可以把一张代金券当做一元花出去,但其不会增加你的消费。

假设你初始有无限的钱和零张代金券,问你花费的钱数最少是多少。

本题有 \(q\) 次修改操作,每次修改会给定两个正整数 \(k\)\(w\),表示将 \(a_k\) 的值改为 \(w\)

\(n \le 3 \times 10^5\)\(1 \le a_i \le 10^{12}\)

标签:贪心、推式子、线段树

solution

考虑消费的最优策略是什么样子的,感受一下即可发现,因为我们会希望得到的代金券都用完,因此一定会倾向于前期攒后期用,进一步地,可以认为是从某个位置 \(p\) 开始,满足 \(p\) 之后的所有元素都是用代金券付清的。

但这个策略并不全对,考虑对于 \(a_i\),因为我们至多只能从第 \(i\) 项获得 \(\lfloor \frac{a_i}{c} \rfloor\) 张代金券,因此在 \(a_i\) 上花费 \(a_i \% c\) 张代金券是没有影响的。因此完整的策略是,每次都尽量在没有影响的部分上花代金券,并在此基础上取前文中的“后缀”花费代金券。

定义 \(x_i = \lfloor \frac{a_i}{c} \rfloor\)\(y_i \equiv a_i \pmod{c}\),则

若每次使用的代金券数量不超过 \(y_i\),则顺序操作完前 \(i\) 项后剩余的代金券数量 \(f_i\) 满足

\[f_i = \max(0, f_{i - 1} - y_i) + x_i \]

因为有修改操作,而每次对每一位都取一个 \(\max\) 会很难维护,于是考虑拆掉这个 \(\max\)

\(g_i = f_i - x_i\),即,对第 \(i\) 项使用完足量代金券且获取新代金券前的代金券数目。我们有:

\[g_i = \max(0, g_{i - 1} + x_{i - 1} - y_i) \]

\(d_i = x_{i - 1} - y_i\),则

\[g_i = \max(0, g_{i - 1} + d_i) \]

故若令 \(s_i\) 表示 \(d\) 的前缀和,即 \(w_i = \sum\limits_{j = 1}^{i} d_j\),则有

\[g_i = w_i - \min\limits_{j = 0}^{i} w_i \]

同理可得

\[f_i = g_i + x_i = w_i - \min\limits_{j = 0}^{i} w_i + x_i \]

然后你考虑刻画后缀上的代金券使用:从某一个点 \(p\) 开始的一段后缀,其中 \(p\) 上的操作不固定,后面则全都是用券全部付完。

取出最右边的使 \(g_i\) 达到全局最小值的位置 \(q\),人类大脑告诉我们 \(p\) 不应该早于 \(q\) 出现,但是理性分析一下可能会发现并非如此,但是再仔细分析一下可能会发现并非并非。

就是,假设 \(p\) 出现在 \(q\) 前面,那道理上你在 \(q\) 上花完代金券了代金券就归零了,而因为 \(q\)\(p\) 后,所以你不会有新的代金券收入,于是后面就爆了;但细心的人类可能会发现 \(q = n\) 时就不用考虑更后面的元素的问题了,不过没关系,我们可以考虑不前于 \(p\)(包括 \(p\)\(p\) 之后的所有元素)\(q\) 之前的元素,因为这些元素上也不会有代金券收入,因此爆的会更早,就是 \(a_q\) 付不完就已经爆了;但研究发现其实还有前面本来就没有代金券收入的情况,这个时候就不会,因为没有代金券收入而爆掉了,但是此时不就等价于 \(p\)\(q\) 后面吗!/hec /hec /hec

这个观察可以大大简化 \(f_p\) 的形式,接下来继续考虑如何快速找到后缀端点 \(p\)。感受一下,肯定是 \(p\) 越往后越更可能合法,下面我们将说明这一点:

因为 \(p\)\(q\) 后面,因此一定有 \(\min\limits_{j = 0}^{i} w_i = \min\limits_{j = 0}^{n} w_i\),考虑写出合法性的判定式:

\[f_i \ge \sum\limits_{j = i + 1}^{n} a_j \]

显然左右两式的 \(Delta\) 都容易被刻画出来。对于左式,即 \(f_i\)(其 \(Delta\)\(f_{i + 1} - f_i\)):

\[f_{i + 1} = f_i + x_i - y_i \]

即有

\[f_{i + 1} = f_i + \lfloor \frac{a_i}{c} \rfloor - (a_i \% c) \]

而对于右式,其 \(Delta\) 显然为 \(-a_i\)

移项,可得到下标 \(i + 1\) 的判定等价于

\[f_i + \lfloor \frac{a_i}{c} \rfloor + a_i - (a_i \% c) \ge \sum\limits_{j = i + 1}^{n} a_j \]

因为左式显然不小于 \(f_i\),因此这个判定式显然不会比下标 \(i\) 的判定式更强!于是合法性具有单调性。

然后你都做到这了,不上个二分就没道理了是不是!有修改操作那就直接线段树二分摁套即可。可能还有一个细节,就是在 \(a_p\) 上花费的代金券数可能要讨论一下得到,当然你也可以直接二分这个东西,虽然会带个 \(O(\log V)\) 但好像也没啥关系。

code

https://qoj.ac/submission/2429858

posted @ 2026-05-23 10:10  zyb_txdy  阅读(14)  评论(2)    收藏  举报