题解 CF538G 【Berserk Robot 】
CF538G Berserk Robot
题意
- 有一个机器人,第
0 秒时在(0,0) 位置。 - 机器人会循环执行一个长度为
l 的指令序列,每秒执行一个指令。 - 指令有
ULDR四种,分别代表向上/左/下/右移动一格。 - 你不知道这个指令序列具体是什么,但是你知道
n 条信息,第i 条信息为「第t_i 秒时机器人在(x_i,y_i) 」,保证t 递增。 - 你需要构造一个满足这些信息的指令序列,或判断不存在。
-
题解
上下左右比较不好做,横纵坐标有关联。
考虑将坐标系逆时针旋转
这样 ULDR 对应的就是
此时原来的
但这样还不够方便,我们考虑将
这样 ULDR 对应的就是
先判掉奇偶性不合法的情况,剩下的只用考虑距离上的约束。
设
对于第
为了方便后面的操作,我们加上
对
将
由于每次只能
即
若
若
若
一共有
具体构造的方法是,确定
对于差分后相邻的两项,可以先从
总时间复杂度
代码
#define Fail prints("NO"), exit(0)
const int N = 2e5 + 7;
const ll inf = 4e18;
int n, l;
ll lx = -inf, rx = inf, ly = -inf, ry = inf;
struct P {
ll t, x, y, k;
int w;
inline void in() {
ll p, q;
rd(t), rd(p), rd(q);
if ((t ^ p ^ q) & 1) Fail;
k = t / l, w = t % l;
x = (p + q + t) / 2, y = (q - p + t) / 2;
}
inline bool operator < (const P &o) const { return w < o.w; }
} p[N];
int main() {
rd(n), rd(l);
for (int i = 1; i <= n; i++) p[i].in();
sort(p + 1, p + n + 1);
p[++n].k = -1, p[n].w = l;
for (int i = 1; i <= n; i++) {
ll k = p[i].k - p[i-1].k;
int w = p[i].w - p[i-1].w;
if (!k) {
if (p[i].x - p[i-1].x - w > 0 || p[i].x - p[i-1].x < 0) Fail;
if (p[i].y - p[i-1].y - w > 0 || p[i].y - p[i-1].y < 0) Fail;
} else if (k > 0) {
lx = max(lx, (ll)ceil(1.0L * (p[i].x - p[i-1].x - w) / k));
rx = min(rx, (ll)floor(1.0L * (p[i].x - p[i-1].x) / k));
ly = max(ly, (ll)ceil(1.0L * (p[i].y - p[i-1].y - w) / k));
ry = min(ry, (ll)floor(1.0L * (p[i].y - p[i-1].y) / k));
} else {
k *= -1;
lx = max(lx, (ll)ceil(1.0L * (p[i-1].x - p[i].x) / k));
rx = min(rx, (ll)floor(1.0L * (p[i-1].x - p[i].x + w) / k));
ly = max(ly, (ll)ceil(1.0L * (p[i-1].y - p[i].y) / k));
ry = min(ry, (ll)floor(1.0L * (p[i-1].y - p[i].y + w) / k));
}
}
if (lx > rx || ly > ry) Fail;
for (int i = 1; i <= n; i++) {
int dx = (p[i].x - p[i].k * lx) - (p[i-1].x - p[i-1].k * lx);
int dy = (p[i].y - p[i].k * ly) - (p[i-1].y - p[i-1].k * ly);
int t = p[i].w - p[i-1].w, x = 0, y = 0;
while (t--)
if (x < dx) {
++x;
if (y < dy) putchar('U'), ++y;
else putchar('R');
} else {
if (y < dy) putchar('L'), ++y;
else putchar('D');
}
}
return 0;
}