序列(seq)
序列(seq)
題目描述
?
?
給定?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 4No提示
?
?
數據范圍和子任務
對于全部的測試數據,保證?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?分):無特殊限制
?
solution
先考慮a*b=n的情況怎么做:連續構造a段下降的b
比如 n=6 a=3 b=2
-> ? ? ?2 1 4 3 6 5
那么如果a>n/b 呢
就把某些段改成升序的
由于每一段之間互不影響,所以這不會改變b的答案
那么n!=a*b 也只是多了一段小段的而已
#include<cstdio> #include<iostream> #include<cstdlib> #include<cstring> #include<algorithm> #include<cmath> #define maxn 100005 using namespace std; int T,n,a,b,ans[maxn],num[maxn]; void init(){for(int i=1;i<=n;i++)ans[i]=num[i]=0; } int main() {freopen("seq.in","r",stdin);freopen("seq.out","w",stdout);cin>>T;while(T--){scanf("%d%d%d",&n,&a,&b);init();if(a+b>n+1){puts("No");continue;}for(int i=1;i<=n;i+=b){int top=i+b-1;top=min(top,n);num[i]=top-i+1;for(int j=top,x=0;j>=i;j--,x++)ans[j]=i+x;}int tmp=n/b;if(n%b)tmp++;if(tmp>a){puts("No");continue;}int tp=a-tmp,i=b+1;while(tp){if(tp>=num[i]-1){for(int j=i;j<=i+num[i]-1;j++)ans[j]=j;tp-=num[i]-1;i=i+b;}else {for(int j=i;j<=i+tp-1;j++)ans[j]=j;for(int j=i+num[i]-1,x=tp;j>=i+tp;j--,x++)ans[j]=i+x;tp=0;}}puts("Yes");for(int i=1;i<=n;i++)cout<<ans[i]<<' ';cout<<endl;}return 0; }?
轉載于:https://www.cnblogs.com/liankewei/p/10358821.html
總結
- 上一篇: [Qualcomm][Debug] 不用
- 下一篇: 第二章:博弈分类