【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_ileq s_{i-1}+1)。
而对于所有的(p_i),我们也可以得到(p_i=lfloor frac {t_i}{l}
floor s_l+s_{t_i mod l}),考虑求出(s_l)从而构造答案。
将所有已知信息按照(t_imod l)从小到大排序,那么对于(forall i,j,t_imod l<t_jmod l),
有
( herefore p_i-p_jleq (lfloor frac {t_i}{l} floor-lfloor frac {t_j}{l} floor)s_lleq p_i-p_j+t_jmod l-t_imod l)
分类讨论一下(lfloor frac {t_i}{l} floor-lfloor frac {t_j}{l} floor)的正负情况就可以得到(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('
');
return 0;
}