杂题选讲20231025

\(\text{CF1809F}\)

题目描述

  • 你在一个有 \(n\) 个点的环上顺时针前进,环上第 \(i\) 个点有两个权值 \(a_i,b_i\),分别代表从点 \(i\) 到点 \(i+1 \bmod n\) 的消耗的油和点 \(i\) 处的油价。你的车的油箱最多只能装 \(k\) 升油,对于每个点,求出从这个点开始顺时针转一圈返回这个点的最小消耗。
  • \(3 \leq n \leq 2\times 10^5,1\leq k \leq 10^9,1\leq a_i\leq k,1\leq b_i\leq2\)

思路点拨

因为题目中有一个特别有意思的性质就是 \(1 \leqslant b_i \leqslant 2\) ,我们可以得出一个贪心策略:我们在能买价格为 \(1\) 的油的时候就尽量买,不得不买价格为 \(2\) 的油才去买。这个策略显然是最优的。

根据上述策略,我们考虑两个节点 \(u,v\) 之间的距离该如何计算(假设 \(u,v\) 之间没有价格为 \(1\) 的油的售卖点),那么我们分类讨论:

  • \(b_u=1\) ,我们计算出两点之间的距离 \(siz\) ,如果 \(k \leqslant siz\) ,那么我们尽量买 \(1\) ,别的买 \(2\) 所以花费是 \(2siz-k\) ;如果 \(siz < k\) ,我们可以全部买价格为 \(1\) 的油,所以花费就是 \(siz\)

  • \(b_u=2\) , 我们只可以购买价格为 \(2\) 的油,花费 \(2siz\)

根据以上贪心策略我们发现如果我们以油价为 \(1\) 的地点分段计算是可以快速求出答案的,问题在于这样单次 \(O(n)\) 并且我们对于每一个起点都需要求一次答案。

注意到这个贡献的计算方式是很好合并的,固可以使用倍增算法优化:我们定义状态 \(f_{i,j}\) 表示从节点 \(i\) 往后跳 \(2^j\) 步的位置,\(g_{i,j}\) 表示从节点 \(i\) 往后跳 \(2^j\) 步的花费。最后简单统计一下答案即可。特别的,我们所只的一步不是从 \(i\)\((i+1) \bmod n\) ,而是指代两两油价为 \(1\) 的点算一步,或者从一个油价为 \(2\) 的点到达之后第一个油价为 \(1\) 的点算一步。

时间复杂度 \(O(n \log n)\)

posted @ 2023-10-25 08:44  Diavolo-Kuang  阅读(7)  评论(0编辑  收藏  举报