zoukankan      html  css  js  c++  java
  • Codeforces 898E Squares and not squares

    题目大意

    给定 $n$($n$ 是偶数,$2le nle 2 imes 10^{5}$)个非负整数 $a_1,dots, a_n$($a_ile 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 $ 个非平方数变成平方数。

  • 相关阅读:
    LeetCode–打印从1到最大的n位数
    常用十大算法(十)— 踏棋盘算法
    常用十大算法(九)— 弗洛伊德算法
    常用十大算法(八)— 迪杰斯特拉算法
    LeetCode–组合
    LeetCode–组合总和
    5513. 连接所有点的最小费用 kruskal
    152. 乘积最大子数组 dp
    1567. 乘积为正数的最长子数组长度 dp
    5481. 得到目标数组的最少函数调用次数. 位运算
  • 原文地址:https://www.cnblogs.com/Patt/p/8052993.html
Copyright © 2011-2022 走看看