K-Stack 2021牛客多校2

链接:https://ac.nowcoder.com/acm/contest/11253/K 来源:牛客网

题目描述

ZYT had a magic permutation a1,a2,⋯ ,an and he constructed a sequence b1,b2,⋯bn by the following pseudo code:

Stk is an empty stack
for i = 1 to n :    
    while ( Stk is not empty ) and ( Stk's top > a[i] ) :
        pop Stk
    push a[i]
    b[i]=Stk's size

But he somehow forgot the permutation a, and only got some k elements of bi.

Construct a permutation a satisfying these bi , or determine no such permutation exists.

Here a permutation refers to a sequence that contains all integers from 1 to n exactly once.

输入描述:

The first line contains two integers n,k(1≤k≤n) — the length of the permutation, the number of  left bi.

Then k lines each contains two integer pi,xi denoting that bpi=xi.

输出描述:

Output one line with n integers a1,a2,⋯an — a possible permutation.

If no such permutation exists, output one integer -1.

示例1

输入

5 2
2 2
5 4

输出

1 2 5 3 4

其实这里的输出样例为1 2 3 5 4 也是可以的,1 2 3 5 4 的输出反而更好理解。

示例2

输入

10 1
1 10

输出

-1

备注:

It's guaranteed that n≤10^6,1≤pi,xi≤n, and ∀i≠j,pi≠pj.

思路:

题意是输出一个符合条件的a数组,保证a数组内元素按照要求依次入栈,第i步操作后栈内元素个数符合b数组对应b[i]的值。

按照伪代码的要求,当栈顶元素大于将要入栈的a[i]的值时,栈顶元素出栈,直到栈顶元素小于等于将要入栈的a[i]的值(注意这里是一个while循环,有可能会一直出栈,所以b数组内后面的元素值比前面的值小是有可能的)。当栈顶元素不大于将要入栈的a[i]的值时,a[i]入栈,更新b[i]为新的栈的大小。

其实也就是一个反推的过程,不理解的话可以手算一下。

但是如果写模拟的代码,可能会超时(当时写的时候确实是超时了,结束之后看别人的代码发现还是有人写模拟的,应该是写的方法问题,需要优化算法)。干脆直接对数组进行操作。

另外要注意,当出现pi的值小于xi的情况,例如pi=2,xi=5,正常情况应该是b2=2,想要在第二次操作b2时实现栈内有5个数,肯定是不可能实现的,当前最多只有2个数。这种情况就要输出-1。

代码:

#include <iostream>
#include <cstdio>
#include <vector>
using namespace std;
int main() {
    ios::sync_with_stdio(false);  
    int n,k;
    cin>>n>>k;
    vector<int> b(n+1);
    while(k--){
        int p,x;
        cin>>p>>x;
        b[p] = x;
    }
    int temp = 0;
    for(int i=1;i<=n;i++){
        temp++;
        if(b[i] > 0){
            if(b[i] > temp){	//当前位置与数字不匹配 
                cout << "-1\n";
                return 0;
            }
            temp = b[i];
        }else b[i] = temp;	//根据所给数据填补b数组 
    }
    vector<int> a(n+2);
    for(int i=1;i<=n;i++){
        a[b[i]]++;			//记录需要变更的数 
    }
    for(int i=2;i<=n+1;i++){
        a[i] += a[i - 1];	//累加前一个的数 
    }
    for(int i=1;i<=n;i++) {
        cout << a[b[i]]-- <<" ";
    }
    cout<<'\n';
    return 0;
}

另外还有类似模拟的代码,附在下面参考

#include <iostream>
#include <cstdio>
#include <stack>
#include <cstring>
using namespace std;
typedef long long ll;
const int N = 1e6+10;
int n,k;
int a[N],b[N],res[N];
stack<int>s;
stack<int>t;

int main()
{
	scanf("%d%d",&n,&k);
    memset(b,0,sizeof(b));
	for(int i=0;i<k;i++){ 
		int p,x;
		scanf("%d%d",&p,&x);
		b[p] = x;
	}
    int temp = 0,flag = 0;
    while(!s.empty()) s.pop();	//清空栈 
    while(!t.empty()) t.pop();	//清空栈
	for(int i=1;i<=n;i++){
        temp++;
        if(b[i] != 0){
            if(temp < b[i]){	//当前位置与数字不匹配 
                flag = 1;		//设置标记 
                break;
            }
            int cnt = temp - b[i];
            for(int j=0;j<cnt;j++){
                t.push(s.top());
                s.pop();
            }
            temp = b[i];
        }
        s.push(i);
    }
    int tot = 1;
    if(flag){
        printf("-1\n");
        return 0;
    }
    while(!s.empty()){
        t.push(s.top());
        s.pop();
    }
    while(!t.empty()){
        res[t.top()] = tot++;
        t.pop();
    }
    for(int i=1;i<=n;i++){
    	printf("%d",res[i]);
    	if(i != n) printf(" ");
    	else printf("\n");
	}
	return 0;
}

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值