Codeforces 898E Squares and not squares
題目大意
給定 $n$($n$ 是偶數,$2\le n\le 2\times 10^{5}$)個非負整數 $a_1,\dots, a_n$($a_i\le 10^9$)。
要求將其中 $n/2$ 個數變成平方數,另外 $n/2$ 個數變成非平方數,變化後的數必須仍是非負整數。
將 $x$ 變成 $x‘$ 的代價為 $|x-x‘|$ 。
求最小的總代價。
比賽時我的思路
用 $c_{i,0}$ 表示將 $a_i$ 變成平方數的最小代價,$c_{i,1}$ 表示將 $a_i$ 變成非平方數的最小代價,不難求出這兩個值。
那麽問題轉化為
從 $c_{1,0}, c_{2,0}, \dots, c_{n,0}$ 和 $c_{1,1}, c_{2,1}, \dots, c_{n,1}$ 中各取出 $n/2$ 個數,限制條件是:$c_{i,0}$ 和 $c_{i,1}$ 不能都取。
求取出的數的最小和。
比賽時我想到這裏就進展不下去了。
轉化後的問題的解法
對於任意一個合法的取數方案,如果不是最優解,則必然存在 $i, j$ 滿足:
- $c_{i,0}, c_{j,1}$ 在所取的數中,且
- $c_{i,0} + c_{j,1} > c_{i,1} + c_{j,0}$ 。
第二個條件可化為
$c_{i,1} - c_{i,0} < c_{j,1} - c_{j,0}$
這樣便得出這個問題的解法:
將下標 $1, 2,\dots,i,\dots, n$ 按 $c_{i,1} - c_{i,0} $ 從小到大排序,對前 $n/2$ 個下標取 $c_{i,1}$,對後 $n/2$ 個下標取 $c_{i,0}$ 。
題解上解法
統計輸入的 $n$ 個數中平方數和非平方數的個數,分別記做 $c_0, c_1$。
若 $c_0 = c_1$ 則無需改變。
若 $c_0 > c_1$ 則需要把 $(c_0 - c_1)/2$ 個平方數變成非平方數。對於非零的平方數,加 1 即可,零則須加 2 。所以,優先改變非零的平方數。
若 $c_0 < c_1$ 則需把 $(c_0 - c_1)/2 $ 個非平方數變成平方數。
Codeforces 898E Squares and not squares