zoukankan      html  css  js  c++  java
  • [Codeforces 864D]Make a Permutation!

    Description

    Ivan has an array consisting of n elements. Each of the elements is an integer from 1 to n.

    Recently Ivan learned about permutations and their lexicographical order. Now he wants to change (replace) minimum number of elements in his array in such a way that his array becomes a permutation (i.e. each of the integers from 1 to n was encountered in his array exactly once). If there are multiple ways to do it he wants to find the lexicographically minimal permutation among them.

    Thus minimizing the number of changes has the first priority, lexicographical minimizing has the second priority.

    In order to determine which of the two permutations is lexicographically smaller, we compare their first elements. If they are equal — compare the second, and so on. If we have two permutations x and y, then x is lexicographically smaller if xi < yi, where i is the first index in which the permutations x and y differ.

    Determine the array Ivan will obtain after performing all the changes.

    Input

    The first line contains an single integer n (2 ≤ n ≤ 200 000) — the number of elements in Ivan's array.

    The second line contains a sequence of integers a1, a2, ..., an (1 ≤ ai ≤ n) — the description of Ivan's array.

    Output

    In the first line print q — the minimum number of elements that need to be changed in Ivan's array in order to make his array a permutation. In the second line, print the lexicographically minimal permutation which can be obtained from array with q changes.

    Sample Input

    4
    3 2 2 3

    Sample Output

    2
    1 2 4 3

    HINT

    In the first example Ivan needs to replace number three in position 1 with number one, and number two in position 3 with number four. Then he will get a permutation [1, 2, 4, 3] with only two changed numbers — this permutation is lexicographically minimal among all suitable.

    题解

    又掉进了题意的坑里...

    一开始以为更换数字的代价是前后数字的差值...结果发现更换代价就是$1$...水得不能再水...

    那显然最小代价就是把多余的数字变成没有的数字。

    对于序列的字典序,也很简单,我们玩一个小贪心,显然数字越小要放越前面。我们将没有的数字从大到小压入栈中。

    从$1$~$n$遍历序列,若扫到重复的元素,如果栈顶元素比它小,显然要替换。若比它大,我们选择跳过(虽然只能跳过一次,但先跳总比后跳好),记录一下,防止之后重复跳两次。

     1 //It is made by Awson on 2017.9.29
     2 #include <set>
     3 #include <map>
     4 #include <cmath>
     5 #include <ctime>
     6 #include <queue>
     7 #include <stack>
     8 #include <vector>
     9 #include <cstdio>
    10 #include <string>
    11 #include <cstring>
    12 #include <cstdlib>
    13 #include <iostream>
    14 #include <algorithm>
    15 #define LL long long
    16 #define Max(a, b) ((a) > (b) ? (a) : (b))
    17 #define Min(a, b) ((a) < (b) ? (a) : (b))
    18 #define sqr(x) ((x)*(x))
    19 #define lowbit(x) ((x)&(-(x)))
    20 using namespace std;
    21 const int N = 200000;
    22 void read(int &x) {
    23     char ch; bool flag = 0;
    24     for (ch = getchar(); !isdigit(ch) && ((flag |= (ch == '-')) || 1); ch = getchar());
    25     for (x = 0; isdigit(ch); x = (x<<1)+(x<<3)+ch-48, ch = getchar());
    26     x *= 1-2*flag;
    27 }
    28 
    29 int n, a[N+5], cnt[N+5];
    30 bool skip[N+5];
    31 stack<int>S;
    32 
    33 void work() {
    34     read(n);
    35     for (int i = 1; i <= n; i++) {
    36         read(a[i]);
    37         cnt[a[i]]++;
    38     }
    39     for (int i = n; i >= 1; i--)
    40         if (!cnt[i]) S.push(i);
    41     printf("%d
    ", S.size());
    42     for (int i = 1; i <= n; i++) {
    43         if (cnt[a[i]] > 1) {
    44             if (skip[a[i]] || a[i] > S.top()) {
    45                 cnt[a[i]]--;
    46                 a[i] = S.top();
    47                 S.pop();
    48             }
    49             else skip[a[i]] = 1;
    50         }
    51     }
    52     for (int i = 1; i <= n; i++) printf("%d ", a[i]);
    53 }
    54 int main() {
    55     work();
    56     return 0;
    57 }
  • 相关阅读:
    算法分类整理+模板②:字符串处理
    【HDU 1687】Lucky Light(思维+计算几何)
    省选总结
    算法分类整理+模板①:矩阵快速幂
    【FZU 1911】Construct a Matrix(矩阵快速幂+找规律)
    【ZOJ 2974】Just Pour the Water(矩阵快速幂)
    博客搬家 from csdn to cnblog
    【FZU 2215】Simple Polynomial Problem(后缀表达式+栈的应用)
    【POJ 1276】Cash Machine(多重背包)
    前端监听图片加载异常-自动替换默认图片
  • 原文地址:https://www.cnblogs.com/NaVi-Awson/p/7610570.html
Copyright © 2011-2022 走看看