[Atcoder] arc91-E LISDL(构造)

[Atcoder] arc91-E LISDL (构造)

题目链接:

E - LISDL

题目大意:

让你构造一个长度为n的排列, 使得整个排列的最长上升子序列长度为A, 最长递降子序列为B。

解题思路:

首先我们要知道什么情况下是不合法的的。、

  1. a + b > n+1 当只有一组递增和一组递降的时候, a+b == n+1
  2. a*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;
}

猜你喜欢

转载自blog.csdn.net/zzzzone/article/details/79672656