Solution - 「AGC006B」 Median Pyramid Easy


给个link

一道挺有意思的构造题

其实有很多种构造方法,这里介绍一种比较好想的方法。

我们想让 \(x\) 作为最顶层的元素,最好的方法就是让 \(x\) 一直处于中间。于是我们就可以使得 \(x\) 左右两边的数都比 \(x\) 小,分别为 \(x - 1\)\(x + 1\),如图
(有点难看)

这里我们可以证明一下 \(x\) 一直处在中间

\(y1 >= x\)\(y2 = x\)

\(y1 < x\)\(y2 = x-1\)

所以 \(y2 =\) \(x\)\(x-1\)

同理

\(z1 <= x\)\(z2 = x\)

\(y1 > x\)\(y2 = x+1\)

所以 \(z2 =\) \(x\)\(x+1\)

综上,无论 \(y2\)\(z2\) 怎么搭配,中间的数一定是 \(x\)

所以我们写程序的时候只用将 \(x-1,x,x+1\) 放在中间即可,其他的数可以随便放置

对于无法构造的情况我们只需判断 \(x\) 是否等于 \(1\)\(2×n+1\)


完整代码

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