题目链接 : Codeforces Round #436 (Div. 2) D
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.
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.
题目大意:
给出n个数,每次可以花费1单位体力来将其中的任意一个数改变为任意一个数。现在他想要将这n个数经过若干次变换,使之包含1-n的所有数字。问他改变完成后花费的最小体力,并输出改变后的序列。如果存在多组解,输出这全排列中字典序最小的哪种方案。
解题思路:
既然花费体力最小,那当然要优先考虑将出现过多次的数字替换为未出现的数字了。然后就是稍微困难点的部分了——字典序最小。
我们考虑一下替换过程中可能会出现的情况可以发现,当一个数要被替换时,如果替换为的数小于这个数,那就取最靠前的数字来进行替换,否则就取靠后的来替换。(如11123 -> 14523, 23334 -> 21354)
接下来的实现,先找一个数组记录这个序列,再找一个来记录每个数字出现的次数。因为最终替换为的是没有出现过的数字,所以还要记录下哪些数字没有出现过,这里可以用set也可以用priority_queue。最后遍历一遍原序列,开始进行替换(即出现次数大于一次的要被没出现过的替换掉)。因为还要比较大小关系,如果被替换的数>要替换的数,直接替换就好了;否则标记下这个数,这里没有替换,以后再遇到不管怎样都要替换掉(再加个vis数组标记一下就好了)。
Mycode:
#include <bits/stdc++.h>
using namespace std;
typedef long long LL;
const int MAX = 200005;
const int MOD = 1e9+7;
const int INF = 0x3f3f3f3f;
int n, tot;
bool vis[MAX];
int a[MAX], b[MAX];
priority_queue <int, vector<int>, greater<int> > Q;
int main()
{
scanf("%d",&n);
for(int i = 1; i <= n; ++i)
{
scanf("%d",&a[i]);
++b[a[i]];
}
for(int i = 1; i <= n; ++i) if(!b[i]) Q.push(i);
for(int i = 1; i <= n; ++i)
{
if(Q.empty()) break;
if(b[a[i]] > 1)
{
if(Q.top() < a[i] || vis[a[i]])
{
++tot;
--b[a[i]];
a[i] = Q.top();
Q.pop();
}
else
vis[a[i]] = true;
}
}
printf("%d\n", tot);
for(int i = 1; i <= n; ++i) printf("%d ", a[i]);
return 0;
}