arc 091 E LISDL

         题意:要求你构造一个长度为n的排列,要求它的最长上升子序列长度为a,最长下降子序列长度为b,不合法输出-1。

         我们可以先分析一下这个n和a,b在满足什么关系的时候是合法的。

         很显然最长上升子序列和最长下降子序列最少可以共用1个位置的数字,那么如果a+b-1大于n了,说明不合法了。

        如果我们令dp[i]=以i结尾的最长上升子序列的长度,那么我们对于每一个dp[i]= 1~a分别考虑。 例如,我们先来考虑dp[i]=1 的那些位置 i, 他们的权值p[i]肯定是递减的,因为如果某个p[i] 大于 之前 dp值=1 的数j了,它的dp值就是2了。这样我们把dp[i]相同的那些位置提出来,它们也构成了一个下降子序列,而且因为最长下降子序列长度为b,那么dp[i]相同的数字不会超过b个。所以我们就有了n<=a*b的这个上界。

         解出来了 a+b-1 <=n <= a*b 这个取值范围,我们就可以找到一种构造方法了。

         我们可以把所有数字分成b组,保证第i组的元素全部大于第i+1组的元素,且第i组内的元素是逐渐递增的。即我们构造的时候第一组放最大的x个,第二组放剩下的最大的y个即可。

         由于n的下界是a+b-1,我们就可以暴力的将第一组分 a个,后面的组肯定至少能分到1个。 对于后面的组,为了防止多出来数字的情况,只要不超过a,我们就可以贪心的往多放,只要保证后面的组至少能放一个即可。 即第i组能放的元素为min(a,n-(i-1))个。这样就愉快的构造出来了。

         下附AC代码。

#include<iostream>
#include<stdio.h>
#include<string.h>
#include<algorithm>
#define maxn 10000005
using namespace std;
int n,a,b,tot;
int ans[maxn];
int main()
{
	scanf("%d%d%d",&n,&a,&b);
	if(n<a+b-1 || n>1ll*a*b)
	{
		printf("-1\n");
		return 0;
	}
 
	for(int i=n-a+1;i<=n;i++)
		ans[++tot]=i;
	n-=a;
 
	b--;
 
	for(int i=b;i>=1;i--)
	{
		int now=min(a,(n-i+1));
		for(int j=n-now+1;j<=n;j++)
			ans[++tot]=j;
		n-=now;
	}
 
	for(int i=1;i<=tot;i++)
		printf("%d ",ans[i]);
}

     

I Am Especially For U 

By ZRX

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值