一道挺有意思的构造题
其实有很多种构造方法,这里介绍一种比较好想的方法。
我们想让
x
x
x 作为最顶层的元素,最好的方法就是让
x
x
x 一直处于中间。于是我们就可以使得
x
x
x 左右两边的数都比
x
x
x 小,分别为
x
?
1
x - 1
x?1 和
x
+
1
x + 1
x+1,如图 (有点难看)
这里我们可以证明一下
x
x
x 一直处在中间
若
y
1
>
=
x
y1 >= x
y1>=x 则
y
2
=
x
y2 = x
y2=x
若
y
1
<
x
y1 < x
y1<x 则
y
2
=
x
?
1
y2 = x-1
y2=x?1
所以
y
2
=
y2 =
y2=
x
x
x 或
x
?
1
x-1
x?1
同理
若
z
1
<
=
x
z1 <= x
z1<=x 则
z
2
=
x
z2 = x
z2=x
若
y
1
>
x
y1 > x
y1>x 则
y
2
=
x
+
1
y2 = x+1
y2=x+1
所以
z
2
=
z2 =
z2=
x
x
x 或
x
+
1
x+1
x+1
综上,无论
y
2
y2
y2 和
z
2
z2
z2 怎么搭配,中间的数一定是
x
x
x
所以我们写程序的时候只用将
x
?
1
,
x
,
x
+
1
x-1,x,x+1
x?1,x,x+1 放在中间即可,其他的数可以随便放置
对于无法构造的情况我们只需判断
x
x
x 是否等于
1
1
1 或
2
×
n
+
1
2×n+1
2×n+1
完整代码
#include <cstdio>
int a[200005], tot = 1;
int main() {
int n, x;
scanf("%d %d", &n, &x);
if (x == 1 || x == 2 * n - 1) {
printf("No");
return 0;
}
printf("Yes\n");
a[n - 1] = x - 1, a[n] = x, a[n + 1] = x + 1;
for (int i = 1; i <= n - 2;) {
if (tot == x - 1 || tot == x || tot == x + 1) tot++;
else a[i] = tot, tot++, i++;
}
for (int i = n + 2; i <= 2 * n - 1;) {
if (tot == x - 1 || tot == x || tot == x + 1) tot++;
else a[i] = tot, tot++, i++;
}
for (int i = 1; i <= 2 * n - 1; i++) {
printf("%d\n", a[i]);
}
return 0;
}
|