Description
Let’s suppose you have an array a, a stack s (initially empty) and an array b (also initially empty).
You may perform the following operations until both a and s are empty:
- Take the first element of a, push it into s and remove it from a (if a is not empty);
- Take the top element from s, append it to the end of array b and remove it from s (if s is not empty).
You can perform these operations in arbitrary order.
If there exists a way to perform the operations such that array b is sorted in non-descending order in the end, then array a is called stack-sortable.
For example, [3, 1, 2] is stack-sortable, because b will be sorted if we perform the following operations:
- Remove 3 from a and push it into s;
- Remove 1 from a and push it into s;
- Remove 1 from s and append it to the end of b;
- Remove 2 from a and push it into s;
- Remove 2 from s and append it to the end of b;
- Remove 3 from s and append it to the end of b.
After all these operations b = [1, 2, 3], so [3, 1, 2] is stack-sortable. [2, 3, 1] is not stack-sortable.
You are given k first elements of some permutation p of size n (recall that a permutation of size n is an array of size n where each integer from 1 to n occurs exactly once). You have to restore the remaining n - k elements of this permutation so it is stack-sortable. If there are multiple answers, choose the answer such that p is lexicographically maximal (an array q is lexicographically greater than an array p iff there exists some integer k such that for every i < k qi = pi, and qk > pk). You may not swap or change any of first k elements of the permutation.
Print the lexicographically maximal permutation p you can obtain.
If there exists no answer then output -1.
Input
The first line contains two integers n and k (2 ≤ n ≤ 200000, 1 ≤ k < n) — the size of a desired permutation, and the number of elements you are given, respectively.
The second line contains k integers p1, p2, …, pk (1 ≤ pi ≤ n) — the first k elements of p. These integers are pairwise distinct.
Output
If it is possible to restore a stack-sortable permutation p of size n such that the first k elements of p are equal to elements given in the input, print lexicographically maximal such permutation.
Otherwise print -1.
Examples
Input |
---|
5 3 3 2 1 |
Output |
3 2 1 5 4 |
Input |
---|
5 3 2 3 1 |
Output |
-1 |
Input |
---|
5 1 3 |
Output |
3 2 1 5 4 |
Input |
---|
5 2 3 4 |
Output |
-1 |
题意:给出某个1~n的排列的一部分,在末尾添上剩余部分,使它成为一个全排列并且满足可栈排序。如果可行,输出字典序最高的答案;如果不行输出-1。
分析:首先需要明白栈排序的原理:一个乱序的全排列a变为顺序的全排列b的过程只有两步:取出a的首部,如果是b期望的下一个数就放入b;或者不能放入b的数暂时入栈。而一旦入栈的数字就只能倒序出栈并且直接进入b,所以出栈的数必须是递增的(因为b是从小到大安放的)。
总结:如果一个全排列是可栈排序的,那么这是一个很强的条件,它必须保证进栈的数必须比栈顶的数小,如果从a取出的数既不能放入b,也不能入栈,那么就一定不是可栈排序的,反正则一定是可栈排序的,因为如果满足上述条件,b期望的下一个数是a和栈的所有数中最小的数,比它更大的数已经全部入栈了,它一定在a的首部,或者在栈的顶端。
思路:先按照要求处理给出的部分,遇到“既不能放入b,也不能入栈”的情况直接判定结果是不行。处理结束后,b期望的下一个数只可能是a的首部,栈顶,或者需要我们来添加。这里就需要判断,如果a的首部和栈顶都不是,是否能添加一个——如果之前出现过了说明期望的数被压在了栈中,是不可行的;如果没有出现过,直接添加就行了。
#include<stdio.h>
//#include<iostream>
//using std::cin;
//using std::cout;
//#include<algorithm>
//using std::sort;
#define max(a,b) ((a)>(b)?(a):(b))
#define min(a,b) ((a)<(b)?(a):(b))
#define mabs(x) ((x)>0?(x):(0-(x)))
#define N_max 200005
int n,m;
int next=1;//b期望的下一个数
int top=0;//栈顶的索引
int stack[N_max];//栈
int done[N_max] = { 0 };//记录哪些数出现过(当前在a,b或栈中)
int ipt[N_max];//输入的数列
void push(int x) {
stack[++top] = x;
}
int pop() {
if (top > 0) return stack[top--] ;
else return -1;
}
int main() {
scanf("%d %d", &n,&m);
for (int i = 0; i < m; ++i) {
scanf("%d", &ipt[i]);
//如果比栈顶小或栈为空就直接入栈
if (ipt[i] < stack[top] || top == 0)
push(ipt[i]);
else {
//处理给定部分时,不允许有不能入栈的情况出现
printf("-1");
return 0;
}
done[ipt[i]] = 1;
//把可以进入b的从栈顶取出
while (stack[top] == next) { next++; pop(); }
}
//处理添加部分
while (top > 0) {
if (next != stack[top]) {
//不能出栈,必须从没用过的数中添加一个到b
if (done[stack[top] - 1] == 0&&m<=n) {
//新添加的数直接记入ipt数组,并更新ipt数组的个数
ipt[m++] = stack[top] - 1;
//更新done数组
done[stack[top] - 1] = 1;
//将添加的部分入栈
push(stack[top] - 1);
}
else {
//既不能出栈,也没有合适的数添加
printf("-1");
return 0;
}
}
//能出栈就出栈
else { pop(); next++; }
}
//栈排空以后,直接按从大到小的顺序,把没用过的数添加到ipt
int next = n;//next记录下一次检索开始的位置,把复杂度降低到O(n)
for (int i = m; i < n; ++i) {
for (int t = next; t >= 1; --t) {//找一个最大的没用过的数
if (done[t] == 0) {
ipt[i] = t; //加入ipt
done[t] = 1; //更新done标记
next = t;//更新next
break;
}
}
}
//输出
for (int i = 0; i < n; ++i) {
printf("%d%c", ipt[i],i==n-1?'\n':' ');
}
}