题意: 给出一个二维 n × m n\times m n×m 的传送带地图,其中>
字符表示当前位置 ( x , y ) (x,y) (x,y) 传送至 ( x , y + 1 ) (x,y+1) (x,y+1),<
表示传送至 ( x , y − 1 ) (x,y-1) (x,y−1),^
表示传送至 ( x − 1 , y ) (x-1,y) (x−1,y)。现在有 q q q 次询问,询问有两种类型,其中A x y
表示询问在点 ( x i , y i ) (x_i,y_i) (xi,yi) 处放置物品,最终会被传送到哪?(物品如果陷入循环则输出-1
,否则物品到达边界则结束),而C x y c
表示修改地图第 ( x , y ) (x,y) (x,y) 坐标位置的传送带为c
类型。
题解: 考虑对 n n n 分块,暴力维护块内每个点的最终位置(要么边界,要么陷入块内陷入循环,要么跳到其它块),这样查询和修改都是 O ( n m ) \mathcal{O}(\sqrt {nm}) O(nm)。维护最终位置的方法是用dp[x][y]
表示点 ( x , y ) (x,y) (x,y) 到达的最终位置,递归地记忆化搜索即可。
代码:
#include
using namespace std;
typedef pair pii;
const int maxn = 1e5 + 5;
char s[maxn][12];
int pos[maxn], L[maxn], R[maxn], n, m, q;
pii dp[maxn][12];
pii dfs(int x, int y, int lim) {
if (dp[x][y].first != 0 || dp[x][y].second != 0) return dp[x][y];
pii res = {0, 0};
if (s[x][y] == '<') {
if (y == 1) res = {x, y-1};
else if (s[x][y-1] == '>') res = {-1, -1};
else res = dfs(x, y-1, lim);
} else if (s[x][y] == '>') {
if (y == m) return res = {x, y+1};
else if (s[x][y+1] == '<') res = {-1, -1};
else res = dfs(x, y+1, lim);
} else if (s[x][y] == '^') {
if (x == lim) res = {x-1, y};
else res = dfs(x-1, y, lim);
}
return dp[x][y] = res;
}
int main() {
scanf("%d%d%d", &n, &m, &q);
int block = sqrt(n + 0.5);
for (int i = 1; i <= n; i++) {
scanf("%s", s[i]+1);
pos[i] = (i-1) / block + 1;
}
int tot = n / block;
if (n % block) tot++;
for (int i = 1; i <= tot; i++) {
L[i] = (i-1) * block + 1;
R[i] = i * block;
if (i == tot) R[i] = min(R[i], n);
for (int j = L[i]; j <= R[i]; j++) {
for (int k = 1; k <= m; k++) dp[j][k] = dfs(j, k, L[i]);
}
}
while (q--) {
char op[2], c[2];
int x, y;
scanf("%s%d%d", op, &x, &y);
if (op[0] == 'C') {
scanf("%s", c);
s[x][y] = c[0];
for (int i = L[pos[x]]; i <= R[pos[x]]; i++) {
for (int j = 1; j <= m; j++) dp[i][j] = {0, 0};
}
for (int i = L[pos[x]]; i <= R[pos[x]]; i++) {
for (int j = 1; j <= m; j++) dp[i][j] = dfs(i, j, L[pos[x]]);
}
} else if (op[0] == 'A') {
while (1) {
if (x == -1 && y == -1) break;
if (x == 0 || y == 0 || x == n+1 || y == m+1) break;
int tx = dp[x][y].first;
int ty = dp[x][y].second;
x = tx, y = ty;
}
printf("%d %d\n", x, y);
}
}
return 0;
}