时间限制: 1 Sec 内存限制: 512 MB Special Judge
提交: 52 解决: 23
[提交][状态][博客][加入收藏]
题目描述
给定 N,A,BN,A,B,构造一个长度为 NN 的排列,使得:
排列长度为 N;
最长上升子序列长度为 A;
最长下降子序列长度为 B。
我们有 SPJ,有解任意给出一组,否则说明无解。
输入
第一行一个整数 TT (1≤T≤101≤T≤10), 表示数据组数.
接下来 T 行,每行三个正整数 N、A、B。
输出
对每组数据:
如果有解,输出两行,第一行一个字符串 Yes,接下来一行 N 个整数,表示排列。
否则, 输出一行一个字符串 No。
样例输入
3
4 2 2
4 4 1
4 3 3
样例输出
Yes
3 4 1 2
Yes
1 2 3 4
No
提示
数据范围和子任务
对于全部的测试数据,保证 T≤10,N≤105,∑N≤2×105T≤10,N≤105,∑N≤2×105
子任务 1(20 分):N≤5N≤5 .
子任务 2(30 分):每组数据均满足 N=A×BN=A×B .
子任务 3(20 分):B≤2B≤2 .
子任务 4(30 分):无特殊限制
来源
hnsdfz国庆集训day2
题解:
对子任务2,由N=AB容易想到将N分为B段长度为A的连续串,要使最长下降子序列长度为B,可以在每段中取一个;使最长上升子序列长度为A,可以在每一段中都递增。那么就要使一段段之间递减(否则就会小于B),且每一段单独递增(否则就会大于B且小于A)。
由子任务2推广到全部数据:同样将N分为B段,且最长一段长度为N,一段段之间递减,单独每一段递增即可。那么考虑不可行的极端情况:1.A+B-1>N,即使除了最长段外每一段长度都为1,也无法生成B段;2.AB<N,即使每段长度都为A,也无法填满。又因为在这种情况下,其他方法也无法填满,故此解为最优。
代码
#include<bits/stdc++.h>
using namespace std;
int R(){
int s=0; char c=getchar(); while(c<'0' || c>'9') c=getchar();
while(c>='0' && c<='9') s=s*10+c-'0',c=getchar(); return s;
}
const int N=1e5+10;
int T,ans[N];
int main()
{
cin>>T;
while(T--){
int n=R(),a=R(),b=R();
if(a+b-1>n || a*b<n) {cout<<"No"<<endl; continue;}
int x,y;
if(a==1) x=0,y=0;
else x=(n-b)/(a-1),y=(n-b)%(a-1)+1;
int t=n+1;
for(int i=1;i<=x;i++){
for(int j=a;j>=1;j--) ans[(i-1)*a+j]=--t;
}
for(int i=x*a+y;i>=x*a+1;i--) ans[i]=--t;
for(int i=x*a+y+1;i<=n;i++) ans[i]=--t;
cout<<"Yes"<<endl;
for(int i=1;i<n;i++) printf("%d ",ans[i]); printf("%d\n",ans[n]);
}
return 0;
}