[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;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章