HDUOJ 6852の増加と減少
問題の説明
注意:1行の終わりに余分なスペースを出力しないでください。
n、x、yが与えられた場合、長さnの順列を作成して、次の条件を満たすようにしてください:
- LIS(Longest Increeasing Subsequence)の長さはxに等しい。
- LDS(Longest Decreasing Subsequence)の長さはyと同じです。
すべての条件を満たす複数の可能な順列がある場合は、辞書式順序で最小のものを出力します。
入力
最初の行には整数T(1≤T≤100)が含まれ、テストケースの数を示します。
各テストケースには、3つの整数n、x、y(1≤n≤1e5,1≤x、y≤n)を含む1行が含まれています。
出力
テストケースごとに、最初の行には「YES」または「NO」が含まれ、回答が存在するかどうかを示します。答えが存在する場合は、順列を示すn個の整数を含む別の行を出力します。
入力例
4
10 1 10
10 10 1
10 5 5
10 8 8
出力例
YES
10 9 8 7 6 5 4 3 2 1
YES
1 2 3 4 5 6 7 8 9 10
YES
1 2 3 5 4 10 9 8 7 6
NO
思考+構造
〜LISの長さはLDSの数であり、LDSの長さはLISの数であることが簡単にわかります〜
出力-1はn≥x ∗ y + 1 n \ geq x * y + 1ですん≥バツ∗そして+1和n <x + y − 1 n <x + y-1ん<バツ+そして−1
以下の構造を考えます。上記の法則に従ってnnを置くことができますnは xxに分割されますグループ xですが、質問は最小の辞書式順序を必要とします。つまり、ブロックを分割するとき、次のブロックはできるだけ大きくする必要があり、回答はスタックに格納できます。ACコードは次のとおりです。
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
int t;
ll n,a,b;
int main(){
scanf("%d",&t);
while(t--){
scanf("%lld%lld%lld",&n,&a,&b);
if(n>=a*b+1||n<a+b-1) printf("NO\n");
else{
printf("YES\n");
stack<int>ans;
while(a){
if(n-b>=a-1){
for(int i=n-b+1;i<=n;i++) ans.push(i);
n-=b;
a--;
}else b=n+1-a;
}
while(!ans.empty()){
printf("%d",ans.top());
ans.pop();
if(!ans.empty()) printf(" ");
else printf("\n");
}
}
}
return 0;
}