翻译
[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;
}

浙公网安备 33010602011771号