B. Build the Permutation (构造一个有a个极大值b给极小值的排列 ) (题目出自Dashboard - Codeforces Round #758 (Div.1 + Div. 2) - Codeforces)
You are given three integers n,a,b. Determine if there exists a permutation p1,p2,…,pn of integers from 1 to n, such that:
-
There are exactly a integers ii with 2≤i≤n−1 such that pi−1<pi>pi+1 (in other words, there are exactly a local maximums).
-
There are exactly b integers ii with 2≤i≤n−1 such that pi−1>pi<pi+1 (in other words, there are exactly b local minimums).
If such permutations exist, find any such permutation.
Input
The first line of the input contains a single integer t (1≤t≤104) — the number of test cases. The description of test cases follows.
The only line of each test case contains three integers n, a and b (2≤n≤10^5).
The sum of n over all test cases doesn't exceed 10^5.
Output
For each test case, if there is no permutation with the requested properties, output −1.
Otherwise, print the permutation that you are found. If there are several such permutations, you may print any of them.(如果有多个符合条件的数列,输出任意一个)
Example
input
3 4 1 1 6 1 2 6 4 0
output
1 3 2 4 4 2 3 1 5 6 -1
题目:让我们用1~n构造一个数列,这个数列有a个极大值,b个极小值
思路:首先可以直接找出无法构造出目标排列的条件,即a和b的差值大于1的情况,和,n-a-b的值<2的情况(a=1,b=1的话至少有4个点才能构造)
然后就是他这个排列需要用1~n去构造。 我的想法是直接弄个排列为n至1的递减数列然后看b为多少,然后将数列的前b个偶数或奇数(分情况讨论)换为1,2,3...这样从最小开始输出,例如:输入n=8,a=2,b=3 输出:8 1 7 2 6 5 3 4 b=3嘛,就将第2,4,6个数换为1,2,3输出,其他数正常输出(具体分情况讨论如下面代码)
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<math.h>
int aa[100000];
int main()
{
int t;
scanf("%d",&t);
while(t--)
{
int n,a,b;
scanf("%d%d%d",&n,&a,&b);//a为极大值个数,b为极小值个数
if( fabs(a-b)>=2||(n-a-b)<2 )printf("-1\n");
else{
for(int i=1;i<=n;i++)
{
aa[i]=i;//数列下标与元素相同
}
if(a<b)//分了3种情况
{ int i=1;//设i为需要实现 将数从小到大输出 的次数
printf("%d",aa[n]);//先打印最大的数,因为输出要求第一个数前面无空格
for(int j=n-1,w=2;w<=n;w++)//w就是数列的第几个数
{
if(w%2==0&&i<b){printf(" %d",aa[i++]);}
//偶数位置的要变小,并且只用实现b-1次(而还有一次在第n-1个数,下个语句)
else if(w==n-1) {printf(" %d",aa[i]);}//自己画个小图很好理解的
else printf(" %d",aa[j--]);//其他情况正常按从大到小输出
}
}
else if(a==b) { int i=1;
printf("%d",aa[n]);
for(int j=n-1,w=2;w<=n;w++)
{
if(w%2==0&&i<=b){printf(" %d",aa[i++]);}//与上面情况不同,这里要实现b次
else {printf(" %d",aa[j--]);}
}
}
else{
int i=1;
for(int j=n,w=1;w<=n;w++)
{ //a>b的情况是在奇数的位置实现将数从小到大进行输出的,实现a次
if(w%2!=0&&i<=a){w==1?printf("%d",aa[i]):printf(" %d",aa[i]);i++;}
else printf(" %d",aa[j--]);//建议自己画图理解
}
}
printf("\n");
}
}
return 0;
}