給定數組 a(長 n)和 b(長 m),可對元素進行 ±1 操作(代價 1)。求最小總代價使 min(a) ≥ max(b)。
存在閾值 x,使調整後 a_i ≥ x 且 b_j ≤ x。
代價函數 f(x) = Σ max(0, x-a_i) + Σ max(0, b_j-x) 是凸函數。
最優 x 必在 a ∪ b 的元素中(或其相鄰整數)。
a_i, b_j 到向量 vals,排序去重。a 前綴和 sa,b 後綴和 sb。x ∈ vals,二分/雙指針計算 f(x),取最小值。ll cost(ll x) {
// a 中 < x 的元素需增加到 x
int pa = lower_bound(a+1, a+n+1, x) - a - 1;
ll c1 = (ll)pa * x - sa[pa];
// b 中 > x 的元素需減少到 x
int pb = upper_bound(b+1, b+m+1, x) - b;
ll c2 = sb[pb] - (ll)(m - pb + 1) * x;
return c1 + c2;
}
sort(a+1, a+n+1); sort(b+1, b+m+1); for (int i=1; i<=n; i++) sa[i] = sa[i-1] + a[i]; for (int i=m; i>=1; i--) sb[i] = sb[i+1] + b[i]; vectorcand; for (int i=1; i<=n; i++) cand.push_back(a[i]); for (int i=1; i<=m; i++) cand.push_back(b[i]); sort(cand.begin(), cand.end()); cand.erase(unique(cand.begin(), cand.end()), cand.end()); ll ans = INF; for (ll x : cand) ans = min(ans, cost(x)); printf("%lld\n", ans);
O((n+m) log(n+m))。n+m,每個 O(log n + log m) 計算代價。O((n+m) log(n+m)),滿足 1e5 規模。O(1)。lower_bound/upper_bound 區分 和 >x。 此題展示了「二分答案 + 前綴和 + 凸性優化」的經典組合,代碼簡潔高效。