CF538G Berserk Robot

题意

  • 给定一些点,要求构造一个操作序列一直循环,使得在特定时间经过那些点

考虑转换坐标系将((x, y))变成((x + y, x - y)),这样向上下左右移动的操作就变成了((+1, -1), (-1, +1), (-1, -1), (+1, +1)),这样就能让(x)坐标与(y)坐标独立开来

于是问题转化为,求一个序列里面只有(-1)(1),要让某个前缀加上一些总和等于某个给定的值,即:

(S)为前缀和

[A_i S_n + S_i = B_i\ S_i = -A_i S_n + B_i ]

所以我们只需要差分一下,让相邻的两个(S)相差的绝对值小于等于位置之差就行:

[|S_i - S_j| leq |i - j| ]

这样就可以解出(S_n)的一个范围,我们任取一个就行

对于相邻的两个(S)我们只需要构造一个序列,使得中间这一段加起来等于它们的差分,解个二元方程即可

#include<bits/stdc++.h>
#define For(i, a, b) for(int i = (a), en = (b); i <= en; ++i)
#define Rof(i, a, b) for(int i = (a), en = (b); i >= en; --i)
#define Tra(u, i) for(int i = hd[u]; ~i; i = e[i].net)
#define cst const
#define LL long long
#define DD double
#define LD long double
#define pb push_back
#define mp make_pair
#define fir first
#define sec second
#define inf 0x3f3f3f3f
#define Inf 0x3f3f3f3f3f3f3f3f
#define eps 1e-12
#define maxn 2000000
using namespace std;

int n, m, a[2][maxn + 5], vis[maxn + 5];
LL t[maxn + 5], pos[2][maxn + 5];
int tt;
struct Node{LL a, b, c;} ord[maxn + 5];

template <class T>
void read(T &x){
	char ch;
	bool ok;
	for(ok = 0, ch = getchar(); !isdigit(ch); ch = getchar()) if(ch == '-') ok = 1;
	for(x = 0; isdigit(ch); x = x * 10 + ch - '0', ch = getchar());
	if(ok) x = -x;
}

int L, R;
void get_rge(LL x, LL y, LL z){
	if(!x) return;
	LD l = (LD)(z - y) / x, r = (LD)(-z - y) / x;
	if(l > r) swap(l, r);
	L = max(L, (int)ceil(l - eps));
	R = min(R, (int)floor(r + eps));
}

int fl = 1;
void sol(int ty){
	memset(vis, 0, sizeof vis);
	memset(ord, 0, sizeof ord);
	For(i, 1, n){
		LL a = -t[i] / m, to = t[i] % m;
		if(to == m - 1){
			if(vis[to]){if(pos[ty][i] / (-a + 1) != ord[to].b){fl = 0; return;}}
			else{
				vis[to] = 1;
				ord[to].b = pos[ty][i] / (-a + 1);
			}
			continue;
		}
		if(vis[to]){
			if(ord[to].a == a && ord[to].b != pos[ty][i]){fl = 0; return;}
			if((pos[ty][i] - ord[to].b) % (ord[to].a - a)){fl = 0; return;}
			LL tem = (pos[ty][i] - ord[to].b) / (ord[to].a - a);
			if(vis[m - 1] && ord[m - 1].b != tem){fl = 0; return;}
			vis[m - 1] = 1;
			ord[m - 1] = (Node){0, tem};
		}
		else{
			vis[to] = 1;
			ord[to] = (Node){a, pos[ty][i]};
		}
	}
	L = ord[m - 1].b; R = ord[m - 1].b;
	if(!vis[m - 1]){
		L = -inf; R = inf;
		int pre = -1;
		For(i, 1, m - 2) if(vis[i]){
			get_rge(ord[i].a - ord[pre == -1 ? m : pre].a, ord[i].b - ord[pre == -1 ? m : pre].b, i - pre);
			pre = i;
		}
		get_rge(1 - ord[pre == -1 ? m : pre].a, -ord[pre == -1 ? m : pre].b, m - 1 - pre);
		if(L > R){fl = 0; return;}
		ord[m - 1].b = L;
		vis[m - 1] = 1;
	}
	ord[m - 1].c = ord[m - 1].b;
	/*if(tt == 146){
		cout << L << " " << R << endl;
		cout << ord[0].a << " " << ord[0].b << endl;
		cout << ord[2000].a << " " << ord[2000].b << endl;
		cout << ord[4000].a << " " << ord[4000].b << endl;
		cout << ord[6000].a << " " << ord[6000].b << endl;
	}*/
	LL tem = ord[m - 1].c, pre = -1;
	For(i, 0, m - 1) if(vis[i]){
		if(i != m - 1) ord[i].c = tem * ord[i].a + ord[i].b;
		if((ord[i].c - ord[pre == -1 ? m : pre].c + i - pre) % 2) break;
		LL tem1 = (ord[i].c - ord[pre == -1 ? m : pre].c + i - pre) / 2;
		if(tem1 > i - pre){fl = 0; return;}
		For(j, pre + 1, pre + tem1) a[ty][j] = 1;
		pre = i;
		if(i == m - 1) return;
	}
	if(tem + 1 >= L && tem + 1 <= R){
		memset(a[ty], 0, sizeof a[ty]);
		tem = ++ord[m - 1].c; pre = -1;
		For(i, 0, m - 1) if(vis[i]){
			if(i != m - 1) ord[i].c = tem * ord[i].a + ord[i].b;
			if((ord[i].c - ord[pre == -1 ? m : pre].c + i - pre) % 2){fl = 0; return;}
			LL tem1 = (ord[i].c - ord[pre == -1 ? m : pre].c + i - pre) / 2;
			if(tem1 > i - pre){fl = 0; return;}
			For(j, pre + 1, pre + tem1) a[ty][j] = 1;
			pre = i;
		}
	}
	else fl = 0;
}

int main(){
	//freopen("in", "r", stdin);
	read(n); read(m);
	For(i, 1, n){
		LL x, y; read(t[i]); read(x); read(y); t[i]--;
		if(i == 2) tt = y;
		LL tem = x;
		x = x + y;
		y = tem - y;
		pos[0][i] = x;
		pos[1][i] = y;
	}
	sol(1);
	if(!fl){puts("NO"); return 0;}
	sol(0);
	if(!fl){puts("NO"); return 0;}
	For(i, 0, m - 1){
		if(!a[0][i] && !a[1][i]) putchar('L');
		if(!a[0][i] && a[1][i]) putchar('D');
		if(a[0][i] && !a[1][i]) putchar('U');
		if(a[0][i] && a[1][i]) putchar('R');
	}
	return 0;
}
原文地址:https://www.cnblogs.com/lprdsb/p/13817720.html