1 条题解

  • 0
    @ 2025-11-10 16:05:37

    算法标签

    前缀和、ST表(稀疏表)、优先队列(堆)、贪心

    问题分析

    我们需要从所有长度在 [L,R][L, R] 之间的连续音符子数组(超级和弦)中,选出 kk 个不同的子数组,使得它们的美妙度之和最大。

    关键观察

    1. 连续子数组的美妙度可以用前缀和快速计算:子数组 [i,j][i, j] 的美妙度为 pre[j]pre[i1]pre[j]-pre[i-1](其中 prepre 是前缀和数组)。
    2. 对于每个左端点 ii,合法的右端点范围是 [i+L1,i+R1][i+L-1, i+R-1],我们需要在这个范围内找到使 pre[j]pre[i1]pre[j]-pre[i-1] 最大的 jj,并通过贪心和堆结构来选择前 kk 大的子数组。

    核心算法思路

    1. 前缀和与ST表预处理

    • 计算前缀和数组 prepre,用于快速得到任意子数组的和。
    • 构建ST表(稀疏表),用于在 O(1)O(1) 时间内查询区间 [l,r][l, r] 内使 pre[j]pre[j] 最大的位置 jj,从而快速得到以 ii 为左端点的最优右端点。

    2. 优先队列(堆)的贪心选择

    • 对于每个左端点 ii,确定其合法右端点范围 [Li,Ri][L_i, R_i]Li=i+L1L_i = i+L-1Ri=i+R1R_i = i+R-1),并找到该范围内使 pre[j]pre[i1]pre[j]-pre[i-1] 最大的 jj,将该子数组的信息(左端点、右端点范围、最优位置、美妙度)存入大根堆。
    • 每次从堆中取出当前最大的子数组,累加到答案中。然后将该子数组的“左半部分”([Li,j1][L_i, j-1])和“右半部分”([j+1,Ri][j+1, R_i])的最优子数组信息重新插入堆中,确保后续能选择到次大的子数组。

    3. 时间复杂度分析

    • ST表预处理:O(nlogn)O(n \log n)
    • 初始入堆操作:O(n)O(n)(每个左端点入堆一次)。
    • 堆操作:每次堆操作是 O(logn)O(\log n),共进行 kk 次,总时间 O(klogn)O(k \log n)
    • 整体时间复杂度为 O(nlogn+klogn)O(n \log n + k \log n),可满足题目中 n5×105n \leq 5 \times 10^5k5×105k \leq 5 \times 10^5 的数据范围。

    总结

    本题通过前缀和快速计算子数组和,ST表快速查询区间最大值位置,结合优先队列(堆)的贪心策略,高效地选出了 kk 个最大的不同超级和弦,从而得到乐曲的最大美妙度。这种方法充分利用了数据结构的特性,在时间和空间复杂度上都能满足题目要求。

    • 1

    信息

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