[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\n");
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\n",ans);
43     for(int i = 1;i <= n;i++){
44         printf("%d ",arr[i]);
45     }
46     
47     return 0;
48 }
D. Make a Permutation!

 

posted @ 2017-09-26 13:42  μSsia  阅读(193)  评论(0编辑  收藏  举报