• 【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_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)

    [egin{aligned} egin{cases} p_i=lfloor frac {t_i}{l} floor s_l+s_{t_i mod l}&(1)\ p_j=lfloor frac {t_j}{l} floor s_l+s_{t_j mod l}&(2)\ 0leq s_{t_j mod l}-s_{t_i mod l}leq t_jmod l-t_imod l end{cases} end{aligned} ]

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

    ( 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; 
    } 
    
  • 相关阅读:
    scala中 object 和 class的区别
    scala中的apply方法与unapply方法
    Scala中的样例类详解
    Scala 中下划线的一些魔法
    Hadoop搭建配置参数调优
    设置ESX/ESXi中(Linux)虚拟机从U盘引导启动
    CentOS下编译安装Busybox
    LRU算法简单实现
    Spark 3.0 动态分区裁剪(Dynamic Partition Pruning)
    Hive中的数据分桶以及使用场景
  • 原文地址:https://www.cnblogs.com/heyujun/p/13393123.html
Copyright © 2020-2023  润新知