[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
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
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\n", 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 }
[Codeforces 864D]Make a Permutation!