题意
要求构造一个1到n的排列,使得该排列的最长上升子序列恰好为a,最长下降子序列恰好为b。若不存在方案则输出-1。
n,a,b<=300000
分析
我们先来思考一下只有上升的该怎么办,很简单,如果我们能分出a段递减的就好了。那如果我们让所有递减的里面的最长的为b就可以满足题目了。
代码
#include <bits/stdc++.h>
int read()
{
int x = 0, f = 1;
char ch = getchar();
while (ch < '0' || ch > '9') {if (ch == '-') f = -1; ch = getchar();}
while (ch >= '0' && ch <= '9') {x = x * 10 + ch - '0'; ch = getchar();}
return x * f;
}
int n,a,b;
int ans[3000005];
int main()
{
n = read(), a = read(), b = read();
if (a == 1)
{
if (b != n)
{
printf("-1\n");
return 0;
}
for (int i = n; i >= 1; i--)
printf("%d ",i);
return 0;
}
int x = (n - b) / (a - 1), y = (n - b) % (a - 1);
if (a > n || b > n || n - b < a - 1 || x + (y > 0) > b)
{
printf("-1\n");
return 0;
}
int tot = 0, now = b;
for (int i = b; i >= 1; i--)
ans[++tot] = i;
for (int i = 1; i <= y; i++)
{
for (int j = now + x + 1; j > now; j--)
ans[++tot] = j;
now += x + 1;
}
for (int i = 1; i <= a - 1 - y; i++)
{
for (int j = now + x; j > now; j--)
ans[++tot] = j;
now += x;
}
for (int i = 1; i <= n; i++)
printf("%d ",ans[i]);
}