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\) 满足:

  1. \(c_{i,0}, c_{j,1}\) 在所取的数中,且
  2. \(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 $ 个非平方数变成平方数。

posted @ 2017-12-17 20:21  Pat  阅读(293)  评论(0编辑  收藏  举报