加载中...

CF|Building Permutation


Codeforces题解|285C - Building Permutation


题目信息 📚

【题目描述】

Permutation $p$ is an ordered set of integers $p_1, p_2, \ldots, p_n$, consisting of $n$ distinct positive integers, each of them does not exceed $n$. We’ll denote the $i$-th element of permutation $p$ as $p_i$. We’ll call number $n$ the size or the length of permutation $p_1, p_2, \ldots, p_n$.

You have a sequence of integers $a_1, a_2, \ldots, a_n$. In one move, you are allowed to decrease or increase any number by one. Count the minimum number of moves needed to build a permutation from this sequence.

【输入】

The first line contains the integer $n$ $(1 \leq n \leq 3 \cdot 10^5)$ — the size of the sought permutation. The second line contains $n$ integers $a_1, a_2, \ldots, a_n$ $(-10^9 \leq a_i \leq 10^9)$.

【输出】

Print a single number — the minimum number of moves.

Please, do not use the %lld specifier to read or write 64-bit integers in C++. It is preferred to use the cin, cout streams or the %I64d specifier.

【输入样例1】

2
3 0

【输出样例1】

2

【输入样例2】

3
-1 -1 2

【输出样例2】

6

【题目来源】

https://codeforces.com/problemset/problem/285/C


题目解析 🍉

【题目分析】

很容易猜到の贪心策略:令排序后的 a[i]i

具体数学证明其实有点困难,多做题提高直觉吧~

来自GPT的证明:

To prove that this approach is optimal, let’s consider two elements $a_i$ and $a_j$ such that $a_i < a_j$ and their corresponding targets in the permutation are $t_i$ and $t_j$ respectively. For the total cost to be minimized, it must be the case that $t_i \leq t_j$.

If $t_i > t_j$, you can swap $t_i$ and $t_j$, which will decrease the total cost because the sum of $|a_i - t_j| + |a_j - t_i|$ is less than $|a_i - t_i| + |a_j - t_j|$. This swap contradicts the assumption that we have an optimal solution.

Thus, for every pair $(a_i, a_j)$ with $a_i < a_j$, their targets must be in non-decreasing order. This ordering is exactly what is achieved by sorting the sequence $a$.

【C++代码】✅

#include<bits/stdc++.h>

using namespace std;
typedef long long LL;
const int N = 3e5 + 10;
int n, a[N];

int main() {
    ios::sync_with_stdio(false);  //cin读入优化
    cin.tie(0);

    // 读入数据并且排序
    cin >> n;
    for (int i = 1; i <= n; i++) cin >> a[i];
    sort(a + 1, a + n + 1);

    // 贪心策略:令排序后的a[i] -> i
    LL cnt = 0;
    for (int i = 1; i <= n; i++) {
        cnt += abs(a[i] - i);
    }
    cout << cnt << endl;

    return 0;
}

文章作者: Rickyの水果摊
版权声明: 本博客所有文章除特別声明外,均采用 CC BY 4.0 许可协议。转载请注明来源 Rickyの水果摊 !
  目录