题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=6852
博客园食用链接:https://www.cnblogs.com/lonely-wind-/p/13485238.html
Notice:Don’t output extra spaces at the end of one line.
Given n,x,y, please construct a permutation of length n, satisfying that:
If there are multiple possible permutations satisfying all the conditions, print the lexicographically minimum one.
Input
The first line contains an integer T ( 1 ≤ T ≤ 100 ) T(1≤T≤100) T(1≤T≤100), indicating the number of test cases.
Each test case contains one line, which contains three integers n , x , y ( 1 ≤ n ≤ 1 0 5 , 1 ≤ x , y ≤ n ) n,x,y(1≤n≤10^5,1≤x,y≤n) n,x,y(1≤n≤105,1≤x,y≤n).
Output
For each test case, the first line contains "YES’’ or "NO’’, indicating if the answer exists. If the answer exists, output another line which contains n integers, indicating the permutation.
Sample Input
4
10 1 10
10 10 1
10 5 5
10 8 8
Sample Output
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
题目大意:给你一个n,你需要构造一个1-n的排列使得其最长上升子序列长度为 x x x,最长下降子序列长度为 y y y
emmm,首先可以肯定的是 x , y x,y x,y是有上限的,对于 x + y > n + 1 x+y>n+1 x+y>n+1的而言直接输出“NO”了。至于其他的我们可以慢慢来探索,
首先我们可以构造一个最长下降子序列为 y y y的 n , n − 1 , n − 2 , . . . , n − y + 1 n,n-1,n-2,...,n-y+1 n,n−1,n−2,...,n−y+1放在最末尾,那么会剩下 n − y n-y n−y个数,接下来我们需要构造 x − 1 x-1 x−1个块来构造最长上升子序列,我们要使其字典序最小,那么也就是说我们尽量在前面只放一个数,而如果 x − 1 x-1 x−1个块每个块放完了还有剩余的数的话我们为了保证字典序最小,那么只能尽量地将大的数往后丢,那么就可以得到:
sz[x]=y;
int p=lst-zu;
for (int i=x-1; i>=1; i--) {
if (p>y-1) {p-=y-1;sz[i]=y;} //如果有多余的数尽量使得后面的块填满
else {sz[i]=p+1;break;}
}
最后将每个块中的数全部倒置就可以了。接下来就是对于“NO”的判断了,神仙队友直接报了个 x ∗ y < n x*y
以下是AC代码:
#include
using namespace std;
#define debug printf("#@$@#$\n")
const int mac=1e5+10;
vector<int>g[mac];
int sz[mac];
int main(int argc, char const *argv[])
{
int t;
scanf ("%d",&t);
while (t--){
memset(sz,0,sizeof sz);
int n,x,y;
scanf ("%d%d%d",&n,&x,&y);
for (int i=1; i<=n; i++) g[i].clear();
int lst=n-y;
int zu=x-1;
if (!zu && y==n) {
printf("YES\n");
for (int i=n; i>=1; i--)
printf("%d%c",i,i==1?'\n':' ');
continue;
}
if (!zu && y!=n) {printf("NO\n"); continue;}
if (x+y>n+1) {printf("NO\n"); continue;}
if (1LL*x*y<n) {printf("NO\n"); continue;}
sz[x]=y;
int p=lst-zu;
for (int i=x-1; i>=1; i--){
if (p>y-1) {p-=y-1; sz[i]=y;}
else {sz[i]=p+1; break;}
}
int cnt=1;
printf("YES\n");
for (int i=1; i<=zu; i++){
if (!sz[i]) {g[i].push_back(cnt++); continue;}
for (int j=1; j<=sz[i]; j++)
g[i].push_back(cnt++);
}
for (int i=1; i<=y; i++){
g[zu+1].push_back(cnt++);
}
for (int i=1; i<=zu+1; i++){
reverse(g[i].begin(),g[i].end());
if (i==zu+1){
for (int j=0; j<g[i].size()-1; j++)
printf("%d ",g[i][j]);
printf("%d",g[i][g[i].size()-1]);
}
else for (auto v:g[i]) printf("%d ",v);
}
printf("\n");
}
return 0;
}