1 条题解

  • 0
    @ 2025-10-19 16:37:12

    题目翻译与题意简述 有 nn 块蛋糕排成一行,每块蛋糕有一个互不相同的美味度 did_i。 Leopold 首先吃掉编号为 aa 的蛋糕,然后每次在空位相邻的两块蛋糕中选择美味度较小的一块吃掉。空位会形成一个连续区间并逐渐扩大。 Molly 会做两种操作:

    E i e:将编号 ii 的蛋糕的美味度提升到第 ee 大(即排名 ee,排名 1 表示最大),保证操作前比它美味的至少有 ee 块。

    F b:询问在吃掉编号 bb 的蛋糕之前,Leopold 已经吃了多少块蛋糕。

    算法思路 核心观察 初始吃掉 aa 后,空位区间是 [a,a][a,a]

    每次在空位区间左边或右边选择美味度更小的蛋糕吃掉,所以空位区间是连续的,且扩展方向由当前区间左右边界外的蛋糕美味度大小决定。

    如果 bbaa 的左边,那么要吃到 bb,必须先把 bbaa 之间的所有蛋糕吃掉,并且可能还要吃掉 aa 右边的一些蛋糕(如果右边蛋糕比左边蛋糕更小,会先吃右边)。

    如果 bbaa 的右边,同理。

    关键性质 设当前空位区间为 [L,R][L,R],要扩展到位置 bbb<Lb < Lb>Rb > R),则:

    b<Lb < L,则必须先把 [b,L1][b, L-1] 全部吃掉,并且可能还要吃掉 R+1R+1 往右的一些蛋糕(如果它们比 [b,L1][b,L-1] 中的最小值还小)。

    b>Rb > R,则必须先把 [R+1,b][R+1, b] 全部吃掉,并且可能还要吃掉 L1L-1 往左的一些蛋糕(如果它们比 [R+1,b][R+1,b] 中的最小值还小)。

    因此,问题转化为:

    对于 b<ab < a: 设 m=mini[b,a1]ord[i]m = \min_{i \in [b, a-1]} \text{ord}[i],其中 ord[i]\text{ord}[i]ii 的美味度排名(排名越小越美味,这里代码里用 ndi+1n-d_i+1 表示排名)。 那么需要往右扩展到第一个美味度排名小于 mm 的位置 xxx>ax > a),答案是 (ab)+(xa)(a - b) + (x - a)

    对于 b>ab > a: 设 m=mini[a+1,b]ord[i]m = \min_{i \in [a+1, b]} \text{ord}[i], 那么需要往左扩展到第一个美味度排名小于 mm 的位置 xxx<ax < a),答案是 (ba)+(ax)(b - a) + (a - x)

    数据结构 用线段树维护区间最小值,支持单点修改和区间最小值查询。

    用两个特殊函数 fdr 和 fdl 分别寻找右边第一个排名小于给定值的位置、左边第一个排名小于给定值的位置。这两个函数可以在线段树上 O(logn)O(\log n) 实现。

    对于 E i e 操作,因为 e10e \le 10,我们直接暴力更新前 10 大蛋糕的排名,并在线段树上单点修改它们的排名值。

    复杂度 建树 O(n)O(n)

    每次 F 操作 O(logn)O(\log n)

    每次 E 操作 O(10logn)O(10 \log n)

    总复杂度 O((n+q)logn)O((n+q)\log n)

    算法标签 线段树(区间最小值、单点修改)

    模拟

    贪心

    数据结构

    代码框架解释 输入与初始化

    读入 n,an, a

    读入 did_i,转换为排名 ord[i]=ndi+1\text{ord}[i] = n - d_i + 1(排名 1 表示最美味的)

    记录前 10 大蛋糕的编号 mstd[]

    线段树

    维护区间最小排名

    build 建树

    qr 查询区间最小排名

    mdf 单点修改排名

    fdr 在区间 [l,n][l, n] 找第一个排名小于 vv 的位置(从右往左方向)

    fdl 在区间 [1,r][1, r] 找第一个排名小于 vv 的位置(从左往右方向)

    处理操作

    E i e:更新前 10 大蛋糕列表,调整排名,并在线段树上修改这些蛋糕的排名值

    F b:根据 bbaa 左/右,分别用上述方法计算答案

    • 1

    信息

    ID
    3111
    时间
    1000ms
    内存
    256MiB
    难度
    10
    标签
    递交数
    6
    已通过
    1
    上传者