You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

求解将k个最短弹簧调整至同长度的最小代价高效算法

将k个最短弹簧调整至同一长度的最小代价最优解法

问题分析

给定已排序的弹簧长度数组x(x₁ ≤ x₂ ≤ ... ≤ xₙ),每个弹簧移动D厘米的代价为1+2+…+D = D*(D+1)/2。对于每个查询k,需计算将前k个最短弹簧调整至同一长度的最小总代价,要求处理n,q ≤ 1e6的大数据量。

核心推导

移动D厘米的代价可展开为:

cost(D) = (D² + D) / 2

总代价为所有弹簧的代价之和,即:

total_cost = (sum(Dᵢ²) + sum(Dᵢ)) / 2

其中Dᵢ = |xᵢ - t|,t为目标长度。要最小化总代价,需同时优化sum(Dᵢ²)和sum(Dᵢ),通过分析可知,最优的t对应前k个元素的中位数附近位置,且可通过前缀和快速计算对应代价。

最优解法步骤

  1. 预处理前缀和与前缀平方和

    • 前缀和数组S:S[k] = x₁ + x₂ + ... + xₖ(S[0] = 0)
    • 前缀平方和数组Sq:Sq[k] = x₁² + x₂² + ... + xₖ²(Sq[0] = 0)
      这两个数组可在O(n)时间内完成计算。
  2. 双指针法确定每个k的最优目标位置
    对于每个k,我们需要找到前k个元素中使总代价最小的位置m(即目标长度为xₘ)。利用双指针维护m:

    • 初始化m = 1
    • 遍历k从1到n:
      • 若m < k且调整到xₘ₊₁的代价更小,则m += 1
      • 记录当前m为opt[k](k对应的最优位置)
        代价差的符号可通过简化公式判断(避免全量计算),确保每个k的处理均摊为O(1),总时间O(n)。
  3. 预处理每个k的最小代价
    对于每个k,利用opt[k]计算最小总代价:

    • 计算sum(Dᵢ²) = Sq[k] - 2*xₘ*S[k] + k*xₘ²
    • 计算sum(Dᵢ) = xₘ*(2m - k) + S[k] - 2*S[m]
    • 总代价为(sum(Dᵢ²) + sum(Dᵢ)) * inv2 % MOD,其中inv2 = 500000004(模1e9+7下2的逆元)
      所有运算需在模1e9+7下进行,注意处理负数(加模后再取模),同时使用64位整数避免溢出。
  4. 处理查询
    每个查询k直接返回预处理好的ans[k],时间O(1),总查询时间O(q)。

关键注意事项

  • 由于xᵢ可达1e9,计算xₘ*xₘ时需用64位整数(如C++中的long long),防止溢出后再取模。
  • 模运算中除法需用逆元替代,2的逆元在1e9+7下为500000004。
  • 双指针法确保了最优位置m的单调递增,保证了预处理的线性时间复杂度。

内容的提问来源于stack exchange,提问作者randomAlgo

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.20 03:29:54