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

    D. Make a Permutation!

    time limit per test 2 seconds
    memory limit per test 256 megabytes
    input standard input
    output standard output
     

    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.

    Examples
    input
    4
    3 2 2 3
    output
    2
    1 2 4 3
    input
    6
    4 5 6 3 2 1
    output
    0
    4 5 6 3 2 1
    input
    10
    6 8 4 6 7 1 6 3 4 5
    output
    3
    2 8 4 6 7 1 9 3 10 5
    Note

    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.

    In the second example Ivan does not need to change anything because his array already is a permutation.

    Analysis

    Ivan有一个数列

    这个数列有重复元素

    我们需要把这个数列变成一个 n 的排列

    改变方式:直接改掉

    当然有很多种方式,在这些排列当中选择更改次数最小的,在更改次数最小的当中选择一个字典序最小的

    (字典序怎么最小:从前往后比,看第一对不同的数字的大小)

    (题目居然还解释这个了)

    被Reek一眼秒Orz

    显然,对于一个带有重复元素的数列

    最小更改次数就是重复元素的数量

    (自行意会= =)

    比如对于一个数列 1 2 2 4 4 3 6 8 5 7

    其中有一个 2 和一个 4 是多余的,如果要将其改成排列,最少次数的操作方式就是把这个 2 和 4 改掉

    那么我们现在维护一个记录着未出现数字的单调队列(队列也行)

    每次遇到重复元素的时候,有两种选择:用一个最小的未出现数字替换掉,或者不这么做,跳过

    根据某些原则:替换如果比不替换优的话我们当然是替换啦,但是有的时候,最小的未出现数字还比这个重复元素大,那么这种情况我们就不替换

    当然肯定也不能放任这个数字重复,因此当该数字出现第二次的时候,无论如何都得换成最小未出现数字

    Code

     1 #include<cstdio>
     2 #include<iostream>
     3 #include<bitset>
     4 #include<queue>
     5 using namespace std;
     6 
     7 bool flag[202020];
     8 int n,cnt,buc[202020],arr[202020],ans;
     9 bitset<202020> buck;
    10 queue<int> Q;
    11 
    12 int main(){
    13     scanf("%d",&n);
    14     
    15     for(int i = 1;i <= n;i++){
    16         scanf("%d",&cnt);
    17         buc[cnt]++;
    18         arr[i] = cnt;
    19         buck.set(cnt);
    20     }
    21     
    22     if(buck.count() == n){
    23         printf("0
    ");
    24         for(int i = 1;i <= n;i++)
    25             printf("%d ",arr[i]);
    26         return 0;
    27     }
    28     
    29     for(int i = 1;i <= n;i++){
    30         if(!buc[i]) Q.push(i);
    31     }
    32     
    33     for(int i = 1;i <= n;i++){
    34         if(buc[arr[i]] > 1 && (arr[i] > Q.front() || flag[arr[i]])){
    35             ans++;
    36             buc[arr[i]]--;
    37             arr[i] = Q.front();
    38             Q.pop();
    39         }else if(buc[arr[i]] > 1) flag[arr[i]] = true;
    40     }
    41     
    42     printf("%d
    ",ans);
    43     for(int i = 1;i <= n;i++){
    44         printf("%d ",arr[i]);
    45     }
    46     
    47     return 0;
    48 }
    D. Make a Permutation!
  • 相关阅读:
    c#构造函数对string类型赋初值
    个人计算机管理
    .net Core2建立MVC网站,部署
    运行或开发.NET Core 的先决条件(支持项目、依赖项)
    在Windows下不使用密码远程登陆Linux
    在Linux下不使用密码远程登陆其他Linux
    如何查看MySQL中每张表占用的空间大小
    pdo如何防止 sql注入
    受教了,memcache比较全面点的介绍,受益匪浅,适用memcached的业务场景有哪些?memcached的cache机制是怎样的?在设计应用时,可以通过Memcached缓存那些内容?
    LVS原理详解及部署之二:LVS原理详解(3种工作方式8种调度算法)
  • 原文地址:https://www.cnblogs.com/Chorolop/p/7596359.html
Copyright © 2011-2022 走看看