1 条题解

  • 0
    @ 2025-10-28 11:56:16

    题意回顾

    给定两个长度为 nn 的序列 aia_ibib_i,构造序列 cc

    • ci{ai,bi}c_i \in \{a_i, b_i\}
    • 恰有 kk 个位置 ci=aic_i = a_i
    • 最小化 max(s,0)\max(s, 0),其中 sscc 的最大子段和

    数据范围:n105n \leq 10^5ai,bi109|a_i|, |b_i| \leq 10^9


    关键观察

    1. 问题转化

    最大子段和 ss 可能为正也可能为负。
    我们要最小化 max(s,0)\max(s, 0),即:

    • 如果能使 s0s \leq 0,答案就是 00
    • 否则要最小化正的最大子段和

    2. 初步思路

    di=biaid_i = b_i - a_i
    如果我们确定哪些位置选 aia_i(集合 AAA=k|A|=k),哪些选 bib_i(集合 BB),则: $ c_i = \begin{cases} a_i & i \in A \\ a_i + d_i & i \in B \end{cases} $ 即 ci=ai+[iB]dic_i = a_i + [i \in B] \cdot d_i


    3. 最大子段和与选择的关系

    最大子段和是序列上一个连续区间的和的最大值。
    我们希望这个值尽量小(非正最好)。

    一个常用技巧:令 xi=citx_i = c_i - t,如果 xx 的最大子段和 0\leq 0,则 cc 的最大子段和 t\leq t
    所以可以二分答案 tt,判断是否存在选择方案使得最大子段和 t\leq t


    4. 二分答案框架

    二分 t0t \geq 0,检查是否存在恰选 kkaia_i 的方案,使得 cc 的任意子段和 t\leq t

    等价于:cc 的最大子段和 t\leq t


    判断可行性(给定 t)

    1. 经典方法:前缀和约束

    pi=j=1icjp_i = \sum_{j=1}^i c_j,则子段和 sum[l,r]=prpl1sum[l,r] = p_r - p_{l-1}
    最大子段和 t\leq t 等价于: $ \forall 0 \leq l < r \leq n,\quad p_r - p_{l-1} \leq t $ 即: $ \forall 0 \leq i < j \leq n,\quad p_j - p_i \leq t $ 这等价于: $ \max_{0 \le i \le n} p_i - \min_{0 \le i \le n} p_i \leq t $


    2. 前缀和与选择的关系

    $p_i = \sum_{j=1}^i a_j + \sum_{j=1}^i [j \in B] \cdot d_j$
    Si=j=1iajS_i = \sum_{j=1}^i a_j(固定),qi=j=1i[jB]djq_i = \sum_{j=1}^i [j \in B] \cdot d_j(由选择决定)。

    pi=Si+qip_i = S_i + q_i

    条件变为: $ \max_{0 \le i \le n} (S_i + q_i) - \min_{0 \le i \le n} (S_i + q_i) \leq t $


    3. 问题转化为:选择 B(大小 n-k)使 q 满足条件

    q0=0q_0 = 0qiq_idjd_jjBj \in B)的前缀和。

    我们希望 max(Si+qi)min(Si+qi)t\max(S_i + q_i) - \min(S_i + q_i) \leq t


    进一步转化

    M=max0in(Si+qi)M = \max_{0 \le i \le n} (S_i + q_i)m=min0in(Si+qi)m = \min_{0 \le i \le n} (S_i + q_i)
    条件 MmtM - m \leq t 等价于:存在常数 CC 使得: mSi+qim+ti m \le S_i + q_i \le m + t \quad \forall i 即: CSi+qiC+ti C \le S_i + q_i \le C + t \quad \forall i 其中 C=mC = m


    4. 调整思路

    我们其实可以控制 qiq_i 来让 Si+qiS_i + q_i 的波动尽量小。
    qiq_i 是某些 djd_j 的和,dj=bjajd_j = b_j - a_j


    解法

    实际上,本题可以用更直接的贪心解法:

    1. 初始全选 bib_i(即 B={1,,n}B = \{1,\dots,n\}A=A = \emptyset
    2. 我们要从 BB 中移出 kk 个元素到 AA(即原本选 bib_i 改成选 aia_i
    3. 每次改变一个位置 iiBBAAcic_i 的变化是 aibi=dia_i - b_i = -d_i
    4. 这会使所有包含 ii 的子段和减少 did_i
    5. 为了最小化最大子段和,我们应优先选择 did_i 最大的位置进行切换(因为这样能最大程度降低正的最大子段和)

    算法步骤

    1. 计算 di=biaid_i = b_i - a_i
    2. did_i 从大到小排序
    3. 初始全选 BB,计算此时的最大子段和 SmaxS_{\max}
    4. 依次将 did_i 最大的 kk 个位置改为选 AA,重新计算最大子段和
    5. 取所有情况的最小 max(s,0)\max(s, 0)

    线性解法思路

    实际上有 O(nlogn)O(n \log n) 解法:

    1. 二分 tt
    2. 用贪心判断:维护前缀和 pp,当 p>tp > t 时,必须将之前某个 bb 改为 aa 来降低前缀和,选择 did_i 最大的位置改
    3. 用堆维护可改的位置

    最终算法()

    • 二分 tt
    • 初始全选 bb,前缀和 sum=0sum=0used=0used=0
    • 用最大堆存当前可选的 (di,i)(d_i, i)
    • 从左到右扫描:
      • sum=sum+bisum = sum + b_i
      • (di,i)(d_i, i) 加入堆
      • 如果 sum>tsum > t
        • 如果堆空或 usedkused \ge k,则不可行
        • 否则弹出堆顶 (d,j)(d, j)sum=sumdsum = sum - dused++used++
    • 最后如果 usedkused \le k 则可行

    这样可在 O(nlogn)O(n \log n) 内检查一个 tt


    总结

    本题的核心是:

    1. 二分答案 tt
    2. 贪心维护前缀和不超过 tt,通过将 bb 改为 aa 来降低前缀和
    3. 优先改 di=biaid_i = b_i - a_i 大的位置
    4. 时间复杂度 O(nlognlogW)O(n \log n \log W),其中 WW 是值域

    通过二分答案和贪心选择,可以高效解决这个看似复杂的最优化问题。

    • 1

    信息

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