【CF538G】Berserk Robot
【CF538G】Berserk Robot
题面
题解
因为如果是上下左右走的话\(x,y\)是相关的,考虑将坐标轴逆时针旋转\(\frac \pi 4\),然后再将坐标乘上\(\sqrt 2\),发现我们现在就是\((-1,-1),(-1,1),(1,-1),(1,1)\)四种位移,如果每次坐标移动再加上时间再除二,也就是\((p_i,q_i)=(\frac {x_i+y_i+t_i}{2},\frac {x_i-y_i+t_i}2)\),每次的位移就变成了\((0,0),(1,0),(0,1),(1,1)\),\(x,y\)方向上的位移也就无关了。
那么\(p_i\)和\(q_i\)的解决方法是一样的,我们考虑解决\(p_i\)。
设在每个长为\(l\)的循环节在前\(i\)个单位时间的位移为\(s_0,s_1...s_l\),那么显然有\(s_{i-1}\leq s_i\leq s_{i-1}+1\)。
而对于所有的\(p_i\),我们也可以得到\(p_i=\lfloor \frac {t_i}{l}\rfloor s_l+s_{t_i\ \bmod\ l}\),考虑求出\(s_l\)从而构造答案。
将所有已知信息按照\(t_i\bmod l\)从小到大排序,那么对于\(\forall i,j,t_i\bmod l<t_j\bmod l\),
有
\(\therefore p_i-p_j\leq (\lfloor \frac {t_i}{l}\rfloor-\lfloor \frac {t_j}{l}\rfloor)s_l\leq p_i-p_j+t_j\bmod l-t_i\bmod l\)
分类讨论一下\(\lfloor \frac {t_i}{l}\rfloor-\lfloor \frac {t_j}{l}\rfloor\)的正负情况就可以得到\(n^2\)组关于\(s_l\)的不等式,但是我们实际上只需要满足相邻的两组就行了所以事实上是\(O(n)\)组不等式就可以确定出\(s_l\)的范围。
确定\(s_l\)后构造的话直接用最近的步数到相邻点然后反复横跳,在最开始除二时判断奇偶性可以判断有没有解以及保证合法。
代码
#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cmath>
#include <algorithm>
using namespace std;
typedef long long LL;
LL gi() {
LL res = 0, w = 1;
char ch = getchar();
while (ch != '-' && !isdigit(ch)) ch = getchar();
if (ch == '-') w = -1, ch = getchar();
while (isdigit(ch)) res = res * 10 + ch - '0', ch = getchar();
return res * w;
}
const int MAX_N = 2e6 + 5;
void Fail() { puts("NO"); exit(0); }
struct node { LL w, a, b; } a[MAX_N], b[MAX_N];
bool operator < (const node &l, const node &r) { return l.w < r.w; }
int N, L, dx[MAX_N], dy[MAX_N];
LL Floor(LL x, LL y) { return (x - (x % y + y) % y) / y; }
LL Ceil(LL x, LL y) { return (x + (y - x % y) % y) / y; }
void solve(node p[], int q[]) {
sort(&p[1], &p[N + 1]);
LL l = 0, r = L;
for (int i = 0; i < N; i++) {
LL x = p[i].b - p[i + 1].b, k = p[i].a - p[i + 1].a, y = x + p[i + 1].w - p[i].w;
if (k > 0) l = max(l, Ceil(x, k)), r = min(r, Floor(y, k));
else if (k < 0) l = max(l, Ceil(y, k)), r = min(r, Floor(x, k));
else if (y < 0 || x > y) Fail();
}
if (l > r) Fail();
LL ls = 0, lw = 0;
for (int i = 1; i <= N; i++) {
LL s = p[i].b - l * p[i].a;
if (p[i].w == lw && s != ls) Fail();
for (int j = lw; j < lw + s - ls; j++) q[j] = 1;
ls = s, lw = p[i].w;
}
}
int main () {
#ifndef ONLINE_JUDGE
freopen("cpp.in", "r", stdin);
#endif
N = gi(), L = gi();
for (int i = 1; i <= N; i++) {
LL t = gi(), x = gi(), y = gi();
if ((x ^ y ^ t) & 1) Fail();
a[i] = (node){(int)(t % L), t / L, (x + y + t) / 2};
b[i] = (node){(int)(t % L), t / L, (x - y + t) / 2};
}
++N;
a[N] = (node){L, -1, 0};
b[N] = (node){L, -1, 0};
solve(a, dx);
solve(b, dy);
for (int i = 0; i < L; i++) putchar("LDUR"[dx[i] << 1 | dy[i]]);
putchar('\n');
return 0;
}