D - Conveyor Belts

思路:分块dp, 对于修改将对应的块再dp一次。

#include<bits/stdc++.h>
#define LL long long
#define fi first
#define se second
#define mk make_pair
#define PII pair<int, int>
#define y1 skldjfskldjg
#define y2 skldfjsklejg
using namespace std;

const int N = 1e5 + 7;
const int M = 1e7 + 7;
const int inf = 0x3f3f3f3f;
const LL INF = 0x3f3f3f3f3f3f3f3f;
const int mod = 1000000007;
int n, m, q, block[N], L[N], R[N];
char s[N][11], op[3];
PII f[N][11];

PII dp(int x, int y, char c, int B) {
    if(x == L[B] - 1 || y == 0 || y == m + 1) return mk(x, y);
    if(f[x][y].fi || f[x][y].se) return f[x][y];
    if(s[x][y] == '>' && c == '<') return f[x][y] = mk(-1, -1);
    if(s[x][y] == '<' && c == '>') return f[x][y] = mk(-1, -1);
    if(s[x][y] == '>') return f[x][y] = dp(x, y + 1, s[x][y], B);
    if(s[x][y] == '<') return f[x][y] = dp(x, y - 1, s[x][y], B);
    return f[x][y] = dp(x - 1, y, s[x][y], B);
}

void update(int B) {
    for(int i = L[B]; i <= R[B]; i++)
        for(int j = 1; j <= m; j++)
            dp(i, j, '^', B);
}

int main() {
    memset(L, -1, sizeof(L));
    memset(R, -1, sizeof(R));

    scanf("%d%d%d", &n, &m, &q);

    for(int i = 1; i <= n; i++) {
        block[i] = i / 300;
        if(L[block[i]] == -1) L[block[i]] = i;
        R[block[i]] = i;
    }

    for(int i = 1; i <= n; i++) {
        scanf("%s", s[i] + 1);
    }

    for(int i = 0; i <= n / 300; i++) update(i);


    while(q--) {
        int x, y;
        scanf("%s%d%d", op, &x, &y);
        if(op[0] == 'C') {
            scanf("%s", op);
            s[x][y] = op[0];
            int p = x / 300;
            for(int i = L[p]; i <= R[p]; i++)
                memset(f[i], 0, sizeof(f[i]));
            update(p);

        } else {
            while((x != -1) && (x >= 1 && x <= n && y >= 1 && y <= m)) {
                int ntx = f[x][y].fi;
                int nty = f[x][y].se;
                x = ntx;
                y = nty;
            }
            printf("%d %d\n", x, y);
        }
    }
    return 0;
}

/*
*/