翻译

[ABC289F] Teleporter Takahashi

首先,我们考虑一维问题:

  • 首先,高桥君位于数轴上的坐标位置\(s\)。我们希望通过重复操作“选择\(a\leq x\leq b\),将高桥君移动到与\(x\)对称的位置”将高桥君移动到\(t\)

当选择\(x\)进行操作时,位于点\(p\)的高桥君会移动到\(2x-p\)\(x=(p+new)\div 2\))。由于\(p\equiv2x-p\pmod2\),当\(s\not\equiv t\pmod2\)时,无论如何都无法从\(s\)移动到\(t\)。以下假设\(s\equiv t\pmod2\)

\(a=b\)时,只能移动到\(s\)\(2a-s\)。进行偶数次操作会将其移动到\(s\),进行奇数次操作会将其移动到\(2a-s\)

\(a\neq b\)时,按顺序操作\(a\)\(a+1\)会使\(p\to p+2\)。按顺序操作\(a+1\)\(a\)会使\(p\to p-2\)。由于\(s\equiv t\pmod2\),可以通过进行\(|s-t|\)次操作将高桥君从\(s\)移动到\(t\)


现在回到二维问题。需要满足\(s_x\not\equiv t_x\pmod2\)\(s_y\equiv t_y\pmod2\)

\(a=b\)\(c=d\)时,根据\(s\)\(t\)的坐标确定操作次数为偶数次或奇数次。

  • \(a=b\)\(t_x\notin\{s_x,2a-s_x\}\)时(即不管怎么变化横坐标都不行)
  • \(c=d\)\(t_y\notin\{s_y,2c-s_y\}\)时(即不管怎么变化纵坐标都不行)
  • \(a=b\)\(c=d\)\(t_x=s_x\)\(t_y = 2c-s_y\)时(尽管二个都满足,但是它们并不是一个奇偶性所对应的)
  • \(a=b\)\(c=d\)\(t_x=2a-s_x\)\(t_y = s_y\)时(尽管二个都满足,但是它们并不是一个奇偶性所对应的)

以上情况的答案为No

如果操作次数确定为偶数次或无法确定,那么\(x\)坐标要么已经匹配,要么相差\(2k\)(其中\(k\neq0\))。如果\(x\)坐标相差\(2k\),则\(a<b\)。此时,可以按顺序操作\((a,c)\)\((a+1,c)\)\((p_x,p_y)\to(p_x+2,p_y)\)。按顺序操作\((a+1,c)\)\((a,c)\)\((p_x,p_y)\to(p_x-2,p_y)\)。因此,可以通过进行\(|s_x-t_x|\)次操作,保持高桥君所在位置的\(y\)坐标不变,将\(x\)坐标与\(s_x\)匹配。

类似地,通过重复操作\((a,c)\)\((a,c+1)\)\((a,c+1)\)\((a,c)\),可以将高桥君所在位置的\(x\)坐标保持不变,将\(y\)坐标与\(s_y\)匹配。

所需操作次数为\(|s_x-t_x|+|s_y+t_y|\leq4\times10^5\lt10^6\),非常小。

如果操作次数确定为奇数次(即不能只用偶数次,那么一定有一维被锁死),可以通过事先对某个点进行操作来将问题转化为偶数次操作的情况。(这样就可以将锁死的一维解放)例如,选择对\((a,c)\)进行操作,则总操作次数为\(1+|(2a-s_x)-t_x|+|(2c-s_y)-t_y|\leq1+8\times10^5\lt10^6\),问题得以解决。

总结如下:

  • 如果\(s_x\)\(t_x\)\(s_y\)\(t_y\)的奇偶性不匹配,则答案为No
  • 如果满足以下情况之一,则答案为No
    • \(a=b\)\(t_x\notin\{s_x,2a-s_x\}\)
    • \(c=d\)\(t_y\notin\{s_y,2c-s_y\}\)
    • \(a=b\)\(c=d\)\(t_x=s_x\)\(t_y = 2c-s_y\)
    • \(a=b\)\(c=d\)\(t_x=2a-s_x\)\(t_y = s_y\)
  • 否则,答案为Yes
  • 如果\(a=b\)\(t_x=2a-s_x\),或者\(c=d\)\(t_y=2c-s_y\),则进行操作\((a,c)\)
  • 如果\(s_x\neq t_x\),则重复操作\((a,c),(a+1,c)\)\((a+1,c),(a,c)\)中合适的操作。
  • 如果\(s_y\neq t_y\),则重复操作\((a,c),(a,c+1)\)\((a,c+1),(a,c)\)中合适的操作。

以下是实现示例。在这类问题中,定义一个将操作和输出结合在一起的函数可能会使代码更易于实现。

(附加:可以找到最短的操作序列。)

#include <iostream>

int main() {
	using namespace std;

	long sx, sy, tx, ty, a, b, c, d;
	cin >> sx >> sy >> tx >> ty >> a >> b >> c >> d;

	// 如果坐标的奇偶性不匹配,则输出 No
	if ((sx ^ tx) % 2 != 0 || (sy ^ ty) % 2 != 0) {
		cout << "No" << endl;
		return 0;
	}

	// 可能性_0:能否通过偶数次操作到达
	// 可能性_1:能否通过奇数次操作到达
	bool 可能性_0{(a != b || sx == tx) && (c != d || sy == ty)};
	bool 可能性_1{(a != b || sx + tx == a + b) && (c != d || sy + ty == c + d)};

	// 如果两者都不可能,则输出 No
	if (!可能性_0 && !可能性_1) {
		cout << "No" << endl;
		return 0;
	}

	// 否则,输出 Yes
	cout << "Yes" << endl;

	// 定义操作函数
	const auto 操作{[&sx, &sy](long x, long y){
		cout << x << " " << y << endl;
		sx = 2 * x - sx;
		sy = 2 * y - sy;
	}};

	// 如果无法通过偶数次操作,则先进行一次操作
	if (!可能性_0) 操作(a, c);

	// 逐步调整坐标,使其相差为2的倍数
	while (sx < tx) { // 增加 x 坐标
		操作(a, c);
		操作(a + 1, c);
	}
	while (sx > tx) { // 减少 x 坐标
		操作(a + 1, c);
		操作(a, c);
	}
	while (sy < ty) { // 增加 y 坐标
		操作(a, c);
		操作(a, c + 1);
	}
	while (sy > ty) { // 减少 y 坐标
		操作(a, c + 1);
		操作(a, c);
	}

	return 0;
}

posted @ 2023-09-08 14:14  wscqwq  阅读(23)  评论(0)    收藏  举报