链接:https://ac.nowcoder.com/acm/contest/51727/A
来源:牛客网
首先看题。题目意思是说,让我们构造一个p[2*n]的数组,其中呢,有一个元素的是确定的,就是那个p[a]=b,还有一个要求,就是说,前面相加的和不能够等于后面相加的和。
现在来看看样例
输入为
3
2 3 4
4 6 1
5 1 3
输出为
3 1 4 2
2 3 7 5 6 1 4 8
3 1 6 10 2 4 7 8 9 5
按照题目的意思,结合样例一分析的话就是 (注:为了方便构造,数组都是从1开始的)
有数组p[4],其中p[3]=4,并且要满足 前面相加的和不能够等于后面相加的和 。即:
p[1]!=p[4] (3!=2)
p[1]+p[2]!=p[3]+p[4] (4!=6)
思路就是呢,因为p[a]=b是固定的,比较好满足,所以主要满足“ 前面相加的和不能够等于后面相加的和 ”这个条件就好了。
知道的是,如果是一串从小到大排好的数组,必满足那个要求( 前面相加的和不能够等于后面相加的和),因为大的数跟大的数相加肯定不会等于小的数。所以,应该是把大的数放在一边,把小的数放在另外一边就好了。
我们以n为分界点,
当a<=n时,可以确定,p[a]是在左边的,b<=n,则说明左边应该是小的那一部分数(左小右大);
依此类推,a>n&&b>n 也是左小右大的情况,而a<=n&&b>n和a>n&&b<=n为左大右小。
所以说,只需要分成两种情况就好了,一个是左小右大,一个是左大右小。
左小右大,此情况,我的思路是
先让数组初始化,从小到大,即p[1]=1, p[2]=2...p[2*n]=2*n。
然后在考虑特殊的p[a]=b,若p[a]!=b,就把p[a]与等于b的p[i]交换一下就好了。
左大右小,就是从大到小初始化数组p[N],基本思路跟上面一样。
代码如下
#include<stdio.h>
#define N 400100
int main()
{
long t,p[N];
scanf("%ld",&t);
while(t--)
{
int n,a,b,i,j=1,t,s;
scanf("%d%d%d",&n,&a,&b);
if((a<=n&&b<=n)||(a>n&&b>n))//左小右大
{
for(i=1;i<=2*n;i++)
{
p[i]=j++;
if(p[i]==b)
s=i;
}
t=p[a];
p[a]=p[s];
p[s]=t;
}
else //if((a<=n&&b>n)||(a>n&&b<=n))//左大右小
{
for(i=2*n;i>=1;i--)
{
p[i]=j++;
if(p[i]==b)
s=i;
}
t=p[a];
p[a]=p[s];
p[s]=t;
}
for(i=1;i<=2*n;i++)
printf("%d ",p[i]);
printf("\n");
}
}