codeforces:Build the Permutation(题解)

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;
 }

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值