codeforces 911E 题解

探讨栈排序的概念,介绍如何通过给定部分排列恢复完整的、字典序最大的可栈排序排列。提供详细的算法思路及Java实现。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

E. Stack Sorting
time limit per test
2 seconds
memory limit per test
256 megabytes
input
standard input
output
standard output

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:

  1. Remove 3 from a and push it into s;
  2. Remove 1 from a and push it into s;
  3. Remove 1 from s and append it to the end of b;
  4. Remove 2 from a and push it into s;
  5. Remove 2 from s and append it to the end of b;
  6. 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 ≤ 2000001 ≤ k < n) — the size of a desired permutation, and the number of elements you are given, respectively.

The second line contains k integers p1p2, ..., 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.

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的一组排列的前k个数字(k<n),按次序入栈,使得某一出栈顺序为1,2,3...n.让我们求出这一组排列,有多个按字典序输出最大的.

思考:

首先处理前k个数字,把这k个数字符合条件的1,2,3..(m-1)的出入栈处理完.如果此时前k个数字已经全部出栈,那么剩下的就是n到m从大到小加入排列即可.

如果前k个数字中还有数字未出栈,那么我们应该先让m,m+1,...(p-1),直到栈顶的数字p,先出栈.(把(p-1)到m从大到小加入到排列中)然后更新栈和m,再重复.

为什么这样做?因为是从小到大顺序出栈,所以(m-1)后面必须跟着m,m+1,...  为什么到(p-1)?如果比p大,那么出栈顺序是m,m+1,...q(>p),p 明显不符合.如果比p小,只是将m=r(<p)而已

那么可见我们的目标就是让前k个数字出栈(前k个两两数字中间的数字会在两者之间入出栈,那么就可达到从小到大出栈的效果),那么剩下的从大到小输出就好.

假设前k个数字中现在栈顶的是p. 1,2,3...(m-1)已经入栈且出栈

1.p>m那么只要在排列中加入(p-1),(p-2)...m,即p-1最先入栈,依次直到m,那么可以让m先出栈,直到p-1出栈,达到升序效果.

2.p<m 不成立,则输出-1

然后重复上述步骤,直至栈空即可,最后添加n, (n-1), ..., m即可

Java实现

[java]  view plain  copy
  1. import java.util.Scanner;  
  2. import java.util.Stack;  
  3.   
  4. public class Main {  
  5.     public static void main(String args[]) {  
  6.         Scanner in = new Scanner(System.in);  
  7.         int n = in.nextInt();  
  8.         int k = in.nextInt();  
  9.   
  10.         //curr表示当前1,2,3,...,(curr-1)已经按顺序出栈  
  11.         int curr = 1;  
  12.   
  13.         int[] a = new int[n*3];  
  14.         Stack<Integer> stack = new Stack<>();  
  15.         for (int i = 0; i < k; i++) {  
  16.             a[i] = in.nextInt();  
  17.             stack.push(a[i]);  
  18.             //判断是否可以连线出栈,如果可以则出栈  
  19.             while ((!stack.empty()) && (stack.peek() == curr)) {  
  20.                 stack.pop();  
  21.                 curr++;  
  22.             }  
  23.         }  
  24.         //index表示下一个要加入排列的数字在a中的下标  
  25.         int index = k;  
  26.         while (!stack.empty()) {  
  27.             //判断是否可以连线出栈,如果可以则出栈  
  28.             while ((!stack.empty()) && (stack.peek() == curr)) {  
  29.                 stack.pop();  
  30.                 curr++;  
  31.             }  
  32.             //如果栈空,说明前k个数字已经完成,可以退出循环  
  33.             if (stack.empty())  
  34.                 break;  
  35.             //1,2,3,...,(curr-1)已经完成出栈,如果栈顶的数字比curr小,说明相悖,输出-1,结束程序  
  36.             if (curr > stack.peek()) {  
  37.                 System.out.println(-1);  
  38.                 System.exit(0);  
  39.             }  
  40.             //栈顶的数字比curr大,则将(p-1)到curr加入排列,然后出栈,更新curr  
  41.             int next = stack.peek();  
  42.             for (int i = next - 1; i >= curr; i--) {  
  43.                 a[index] = i;  
  44.                 index++;  
  45.             }  
  46.             curr = next + 1;  
  47.             stack.pop();  
  48.         }  
  49.         //如果最后一部分还没加入排列,则加入.  
  50.         if (curr <= n) {  
  51.             for (int i = n; i >= curr; i--) {  
  52.                 a[index] = i;  
  53.                 index++;  
  54.             }  
  55.         }  
  56.   
  57.         for (int i = 0; i <n; i++) {  
  58.             System.out.print(a[i] + " ");  
  59.         }  
  60.     }  
  61. }  


参考:http://blog.youkuaiyun.com/Mitsuha_/article/details/78940009

http://blog.youkuaiyun.com/oneday_pyf/article/details/78960255

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值