[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;
}