2021牛客暑期多校训练营2 K:Stack (构造)

题目大意

原题链接:K:Stack
给你一个b序列中的k个位置的数,让你构造一组满足要求的a序列,其中bi代表a数组中第i个数作为结尾的最大上升子序列的长度为bi,而a数组是一个1-n的全排列,每个数不重复。若无法构造,输出-1。


思路

首先我们假设先不考虑a数组是一个全排列,即不用管不重复的问题,那我们首先将所有已给的k个数放在他相应的位置。然后将其他没确定的数,从前往后依次给定,我们给他赋值为前一个数加一。这样我们确定的一个序列一定是满足题意的,只是会有数字重复。
举个例子,加入我们给定b的第四位是1,第五位是2,那我们通过上述方法能得到序列:1 2 3 1 2 2,我们发现这个序列就是满足要求的,因为我们只是构造1.2.3…这样的简单序列,并且满足他所给定的k个位置的要求。
那么接下来我们只需要在把不重复这个条件加进去就好了。我们用一个栈stk来从后往前处理。因为前面数的结果不会影响到后面的数,而后面的数会影响到前面数的结果,比如后面来一个更小的数,就会影响到前面的结果。我们用一个val来计唯一的数值(从1开始,从小往大),如果bi>stk栈中数的个数,我们就一直入栈,直到bi=stk中的数个数,这样栈中的数猜会满足我们当前bi所需要的结果,然后给bi分配栈顶元素,栈顶出栈,继续往前。
我们还要考虑一个合法性的判断,每一位的bi一定不会币前一位大超过1,即 b i − b i − 1 > 1 b_i-b_{i-1} > 1 bibi1>1时,时非法的,直接输出-1即可,因为此时只增加了一位数,却在结果中增加了大于1个的数,此时一定非法,其他情况都合法。
用上述方法首先因为val的原因,不会出现相同的数,而且对于每一位的bi,我们都在栈中放了满足该bi所需要的数,然后再往前分配,这样出来的结果一定是合理的,如果不明白没关系,看着代码手推一遍很快就懂了,下面 是代码。


AC代码

#include<iostream>
using namespace std;
const int N = 1000010;

int n,k,top,val,a[N],b[N],stk[N];

int main()
{
	cin >> n >> k;
	while(k--)
	{
		int x,p;
		cin >> x >> p;
		b[x] = p;
	}
	for(int i = 1;i <= n;i++)
	{
		if(b[i] == 0)
			b[i] = b[i-1] + 1;		//不考虑重复,构造完b数组
		else
			if(b[i] - b[i-1] > 1)
			{
				cout << -1 << endl;
				return 0;
			}
	}
	for(int i = n;i > 0;i--)		//根据b数组用stk栈来分配val到a数组
	{
		while(b[i] > top)		//当前位需要bi个数,因此栈中就放bi个数来满足该位
			stk[++top] = ++val;
		a[i] = stk[top--];		//给当前位分配栈顶元素
	}
	for(int i = 1;i <= n;i++)
		cout << a[i] << " ";

	return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值