Loading

CF331D2 Escaping on Beaveractor 题解

考场上上厕所的时候灵机一动,为什么不倍增呢?

考虑如何倍增。

\(f[s][dir][x][y] = \{x',y',di'\}\)

表示从点 \((x,y)\) 开始以 \(dir\) 的方向走 \(2^s\) 步,走到了点 \((x',y')\) ,在 \((x',y')\) 上的方向为 \(di'\)

先处理出走一步(\(2^0\) 步)的情况:输入传送带时把传送带上所有点打上方向标记,走一步时考虑目前处于的点和将要到达的点是否在传送带上即可。

然后逐步合并,直到 \(2^{50}>1e15\) 步。

但是出现了问题,空间复杂度为 \(O(3\times4\log_2{1e15} b^2)\),算出来要开 \(6e8\)\(int\),根本开不下。

但我们发现,题目里并没用要求强制在线,于是我们先把询问都离线下来。

使用滚动数组:对于每个 \(s\),检查每个 \(\text{lowbit}(x)\) 是否等于 \(2^s\),若是,进行倍增。然后合并成 \(s+1\)

这样空间复杂度就变为了 \(O(3\times4b^2)\),时间复杂度 \(O(3\times4\log_2{1e15} b^2 + q\log_2t)\),虽然看起来很极限,但是能过。

点击查看代码
int n , b , m , a[N][N];

struct elem {
	int x , y , d;
};
elem f[2][5][N][N];

struct QUERY {
	int x , y , di;
	ll t;
}q[N * 100];

//#define Up 1
//#define Down 2
//#define Right 3
//#define Left 4
int mp[256];
int dx[] = {0 , 0 , 0 , 1 , -1};
int dy[] = {0 , 1 , -1 , 0 , 0};
#define lowbit(x) ((x) & (-(x)))
signed main(){
	freopen("C.in" , "r" , stdin);
	freopen("C.out" , "w" , stdout);
	
	mp['U'] = 1 , mp['D'] = 2;
	mp['R'] = 3 , mp['L'] = 4;
	n = read() , b = read();
	for(int i = 1; i <= n; ++ i){
		int x = read() , y = read() , X = read() , Y = read();
		if(x == X){
			if(y < Y) for(int j = y; j <= Y; ++ j) a[x][j] = 1;
			else for(int j = Y; j <= y; ++ j) a[x][j] = 2;
		}
		else {
			if(x < X) for(int j = x; j <= X; ++ j) a[j][y] = 3;
			else for(int j = X; j <= x; ++ j) a[j][y] = 4;
		}
	}
	
	for(int i = 0; i <= b; ++ i){
		for(int j = 0; j <= b; ++ j){
			for(int di = 1; di <= 4; ++ di){
				int nx = i + dx[di];
				nx = max(nx , 0); nx = min(nx , b);
				int ny = j + dy[di];
				ny = max(ny , 0); ny = min(ny , b);
				int nd;
				if(a[nx][ny]) nd = a[nx][ny];
				else nd = di;
				f[0][di][i][j] = {nx , ny , nd};
			}
		}
	}
	m = read();
	for(int i = 1; i <= m; ++ i){
		int x = read() , y = read();
		int di = mp[readc()];
		if(a[x][y]) di = a[x][y];
		ll t = read();
		q[i] = {x , y , di , t};
	}
	for(int s = 0; s <= 50; ++ s){
		for(int i = 1; i <= m; ++ i){
			int x = q[i].x , y = q[i].y;
			int di = q[i].di , t = q[i].t;
			if(lowbit(q[i].t) == (1LL << s)){
				auto tmp = f[s & 1][di][x][y];
				q[i].x = tmp.x;
				q[i].y = tmp.y;
				q[i].di = tmp.d;
				q[i].t -= lowbit(q[i].t);
			}
		}
		if(s != 50){
			for(int di = 1; di <= 4; ++ di){
				for(int i = 0; i <= b; ++ i){
					for(int j = 0; j <= b; ++ j){
						auto tmp = f[s & 1][di][i][j];
						int nx = tmp.x , ny = tmp.y , nd = tmp.d;
						tmp = f[s & 1][nd][nx][ny];
						f[(s + 1) & 1][di][i][j] = tmp;
					}
				}
			}
		}
	}
	for(int i = 1; i <= m; ++ i){
		writesp(q[i].x) , writeln(q[i].y);
	}
	
	return 0;
}
posted @ 2024-05-11 15:41  TongKa  阅读(31)  评论(0)    收藏  举报