[Atcoder] arc91-E LISDL (构造)
题目链接:
题目大意:
让你构造一个长度为n的排列, 使得整个排列的最长上升子序列长度为A, 最长递降子序列为B。
解题思路:
首先我们要知道什么情况下是不合法的的。、
a + b > n+1
当只有一组递增和一组递降的时候, a+b == n+1a*b < n
最多的时候, 有a组递降序列, 每组序列长度为b。 最多构成a*b长度。
然后就是分组构造, 一共构造b组, 每组构造长度为min(a,n-(b-1))
的递增序列。 理解:要保持长度不能大于a, 并且剩余的个数要能够构造出b-1组递降。
最后 小心爆int
参考博客:feng_zhiyu
AC代码:
/********************************************
*Author* :ZZZZone
*Created Time* : 日 3/11 21:07:02 2018
* Ended Time* : 五 3/23 15:03:27 2018
*********************************************/
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#include <vector>
#include <queue>
#include <set>
#include <map>
#include <string>
#include <cmath>
#include <cstdlib>
#include <ctime>
#include <stack>
using namespace std;
typedef pair<int, int> PII;
typedef long long LL;
typedef unsigned long long ULL;
const int MAXN = 3e5;
inline void OPEN(string s){
freopen((s + ".in").c_str(), "r", stdin);
freopen((s + ".out").c_str(), "w", stdout);
}
LL n, a, b;
void solve()
{
if(a+b>n+1||a*b<n)///第一个条件很容易知道 第二个条件就写写找找看吧。。
{
cout<<-1;
return ;
}
while(n>0)///每轮都是构造一个递增的子序列
{
LL x=min(a,n-b+1);///每一轮都取递增数和递减数中较小的那个
//cout<<"x="<<x<<endl;
for(LL i=n-x+1;i<=n;i++)
cout<<i<<" ";
n-=x;///x 为这一轮构造的递增子序列的个数
b--;///递减的值 b 每一轮 -1
}
}
int main()
{
while(cin>>n>>a>>b)
{
solve();
cout<<endl;
}
return 0;
}