🍕🏠🌋 当前时间是:

 

CF1495F

传送门

decription

给定 \(n\) 和长度为 \(n\) 的排列 \(p\)。在一个位置 \(i\) 可以采取如下行动:

  • 花费 \(a_i\) 走到 \(i+1\)

  • 如果 \(p_i\) 后存在一个 \(p_j>p_i\),则可以花费 \(b_i\) 跳到 \(j\),否则可以花费 \(b_i\) 跳到 \(n+1\)

希望最小化从 \(1\)\(n+1\) 的花费。此外还有限制:有必经点集合 \(S\),必须经过 \(S\) 内每一个点。

\(m\) 次询问,每次询问的 \(S\) 都是上一次询问的 \(S\) 加上或删除一个元素。每次询问输出最小花费。

  • \(n,m\leq 2\times 10^5\)

  • \(-10^9\leq a_i,b_i \leq 10^9\)

solution

\(S\) 集合是有序的且 \(S_{0}=1,S_{|S|+1}=n+1\)

第一步转化是求 \(1\)\(n+1\) 的最小花费转化成求 \(S_{i}\)\(S_{i+1}(0\leq i\leq |S|)\) 的花费和的最小值。每一部分是独立的,所以要求每一段的花费的最小值。

每次给集合 \(S\) 加点删点相当于加上或删除共三段的贡献。计算答案的差分数组就可以了(也就是三段最小花费带来的答案变化量)。

问题就变成了有 \(O(m)\) 次询问 \([l,r]\),求 \(l\)\(r\) 的最小花费。

关键的一步是考虑把所有询问离线下来,右端点递增排序。

我们只需要顺次维护 \(1,2,3,\dots n+1\) 位置为终点时它前面的点到它的最小花费。

考虑这个图的性质:设 \(nxt_{i}\) 表示第 \(i\) 个位置下一个比它大的位置(不存在则为 \(n+1\)),那么对于 \(i<j,p_i>p_j\),一定有 \(nxt_{j}\leq nxt_{i}\)

这说明右端点为 \(r\) 的时候直接加边不会对之前加的边减小的花费造成影响。

直接树状数组维护就行了。

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

code

Submission #231468601 - Codeforces

posted @ 2023-11-16 11:58  zzafanti  阅读(22)  评论(0)    收藏  举报
浏览器标题切换
浏览器标题切换end