2026.7 做题记录

  1. P2048

    大名鼎鼎的超级钢琴.显然考虑前缀和的差.

    法一:

    尝试规约成简单问题.假设我们能够知道第 \(k\) 大的 \(s_j - s_i\),设为 \(M\),于是问题大致划分为求 \(M\) 和求不小于 \(M\) 的 \(s_j - s_i\) 的和.

    先二分答案求 \(M\).对于每个 \(j = L, \dots, n\),统计 \(\left[ \max\{ j - R, 0 \}, j - L \right]\) 中有多少个 \(i\) 满足 \(s_i \le s_j - M\).相当于是固定宽度的二维数点,可以用树状数组统计,需要离散化.由于卡常,需要精细实现以减小常数.顺便求出符合的 \((i,j)\) 个数 \(cnt\),答案是不小于 \(M\) 的 \(s_j - s_i\) 的和减去 \((cnt - k) \times M\).对于这个和,仍然遍历 \(j\),显然可以用小根堆维护全体备选的 \(s_i\).

    实际上,由于恰好等于 \(M\) 的 \(s_j - s_i\) 可能很多,上述做法复杂度会假掉.正确的修正方案是改为计算严格大于 \(M\) 的 \(s_j - s_i\) 的和,统计这部分的 \((i,j)\) 数 \(cnt^{\prime}\),再加上 \((k - cnt^{\prime}) \times M\).

    以上做法有 \(O(n\log n\log S + k\log n)\) 的时间复杂度.其中 \(S = \sup \sum_{i=1}^{n} |a_i| = 5 \times 10^8\).

    法二:

    经典做法.对每个 \(j = L, \dots, n\),用堆维护 \(f(l, r, j)\) 表示以 \(j\) 为右端点,左端点在 \([l, r]\) 中选取,能取到的最大值.取出 \(f(l, r, j)\) 后 \(f(l, i - 1, j)\) 和 \(f(i + 1, r, j)\) 入堆.正确性在于每次取到的都是剩下的可能性中最大的,且不重不漏.时间复杂度 \(O(n\log n + k\log (n + k))\).

posted @ 2026-07-07 15:40  BrainLE  阅读(8)  评论(0)    收藏  举报