a242: 第三題:絕對值總和的最小值

Tags: math


出處:https://zerojudge.tw/ShowProblem?problemid=a242
提交:https://zerojudge.tw/Submissions?problemid=a242&account=allllllan123456


問題:給你一個正整數 $n\in[1,100000]$ 以及 $2n$ 個正整數 $a_1$, $x_1$, $a_2$, $x_2$, …, $a_n$, $x_n$,其中 $\displaystyle\sum_{i=1}^n a_i\le200000$ 而且 $a_i | x_i$ for all $i$,求 $\displaystyle\sum_{i=1}^n|a_ix - x_i|$ 的最小值。


解法:看到絕對值 $|x-x_i|$ 就要想成數線上 $x$ 和 $x_i$ 兩數的距離,因此我們可以先把原本的 $|a_ix - x_i|$ 都先解壓縮成 $a_i\cdot|x - x_i/a_i|$,原式於是展成 $\displaystyle\sum_{i=1}^{n'}|x - x_i'|$。讓 $x_1'\le x_2'\le …\le x_n'$,那麼讓頭尾兩兩一組,易知 $|x - x_1'| + |x - x_n'|$ 在 $x\in[x_1', x_n']$ 時會有最小值 $x_n' - x_1'$,而 $|x - x_2'| + |x - x_{n-1}'|$ 在 $x\in[x_2', x_{n-1}']$ 時有最小值 $x_{n-1}' - x_2'$,依此類推,因此當 $x$ 為 $x_1',\ x_2',\ …,\ x_n'$ 的中位數時能讓每一組都有各自的最小值,那它們加起來就是整體的最小值了。


 1#include <bits/stdc++.h>
 2using namespace std;
 3
 4int main() { ios_base::sync_with_stdio(false); cin.tie(nullptr); // IO 優化
 5    int m; cin >> m;
 6    while (m--) { long long ans = 0;
 7        int n; cin >> n; int vLen=0, v[200000];
 8        while (n--) {
 9            int a, x; cin >> a >> x;
10            int t = x / a;
11            while (a--) v[vLen++] = t;
12        }
13        sort(v, v+vLen);
14        for (int i=0; i<vLen-1-i; i++)
15            ans += v[vLen-1-i] - v[i];
16        cout << ans << '\n';
17    }
18    return 0;
19}

no image