【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\)

\[\begin{aligned} \begin{cases} p_i=\lfloor \frac {t_i}{l}\rfloor s_l+s_{t_i\ \bmod\ l}&(1)\\ p_j=\lfloor \frac {t_j}{l}\rfloor s_l+s_{t_j\ \bmod\ l}&(2)\\ 0\leq s_{t_j\ \bmod\ l}-s_{t_i\ \bmod\ l}\leq t_j\bmod l-t_i\bmod l \end{cases} \end{aligned} \]

\[\begin{aligned} (1)-(2): &p_i-p_j=\lfloor \frac {t_i}{l}\rfloor s_l+s_{t_i\ \bmod\ l}-\lfloor \frac {t_j}{l}\rfloor s_l-s_{t_j\ \bmod\ l}\\ \Leftrightarrow &(\lfloor \frac {t_i}{l}\rfloor-\lfloor \frac {t_j}{l}\rfloor)s_l=s_{t_j\ \bmod\ i}-s_{t_j\ \bmod\ l}+p_i-p_j \end{aligned} \]

\(\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; 
} 
posted @ 2020-07-28 19:00  heyujun  阅读(258)  评论(2编辑  收藏  举报