E-MAZE_2019牛客暑期多校训练营(第二场)

题意

给出n行m列的迷宫0可走1不可走,有两个操作,操作1变换点(a,b)的值,操作2查询(1,a)到(n,b)的方案数

题解

(F[i][j])为第i-1行到达第i行第j列的方案数,若点((i,j))上下为0的可延伸范围为((l,r)),则(F[i][j] = sum_{k=l}^r F[i-1][k])
由这个式子就可以构造出第i-1行到第i行方案数的转移矩阵,用线段树维护一下区间矩阵乘积

代码

#include <cstdio>
#include <cstring>
#include <algorithm>
#include <queue>
#include <bitset>

using namespace std;
typedef long long ll;
const int mx = 5e4+5;
const int mod = 1e9+7;
char mp[mx][12];
int n, m, q;

struct Matrix {
    ll a[12][12];
    Matrix() {memset(a, 0, sizeof(a));}
    Matrix(int op) {
        memset(a, 0, sizeof(a));
        for (int i = 1; i <= m; i++) a[i][i] = 1;
    }
    Matrix operator * (Matrix other) const{
        Matrix tmp = Matrix();
        for (int i = 1; i <= m; i++) {
            for (int j = 1; j <= m; j++) {
                for (int k = 1; k <= m; k++) {
                    tmp.a[i][j] += a[i][k] * other.a[k][j] % mod;
                    tmp.a[i][j] %= mod;
                }
            }
        }
        return tmp;
    }
}mat[mx<<2];

void pushUp(int rt) {
    mat[rt] = mat[rt<<1] * mat[rt<<1|1];
}

void InitData(int pos, int rt) {
    mat[rt] = Matrix();
    for (int i = 1; i <= m; i++) {
        for (int j = i; j <= m && mp[pos][j] == '0'; j++) {
            mat[rt].a[j][i] = 1;
        }
        for (int j = i; j >= 1 && mp[pos][j] == '0'; j--) {
            mat[rt].a[j][i] = 1;
        }
    }
}

void build(int l, int r, int rt) {
    if (l == r) {
        if (r == 1) mat[rt] = Matrix(0);
        else InitData(r, rt);
        return;
    }
    int mid = (l + r) / 2;
    build(l, mid, rt<<1);
    build(mid+1, r, rt<<1|1);
    pushUp(rt);
}

void update(int pos, int l, int r, int rt) {
    if (pos == 1) return;
    if (l == pos && r == pos) {
        InitData(pos, rt);
        return;
    }
    int mid = (l + r) / 2;
    if (pos <= mid) update(pos, l, mid, rt<<1);
    else update(pos, mid+1, r, rt<<1|1);
    pushUp(rt);
}

int main() {
    scanf("%d%d%d", &n, &m, &q);
    for (int i = 1; i <= n; i++) scanf("%s", mp[i]+1);
    build(1, n, 1);
    while (q--) {
        int op, a, b;
        scanf("%d%d%d", &op, &a, &b);
        if (op == 1) {
            mp[a][b] = (mp[a][b] == '1' ? '0' : '1');
            update(a, 1, n, 1);
        } else {
            Matrix ans = mat[1];
            int s[12] = {0};
            for (int i = a; i <= m && mp[1][i] == '0'; i++) s[i] = 1;
            for (int i = a; i >= 1 && mp[1][i] == '0'; i--) s[i] = 1;

            ll res = 0;
            for (int i = 1; i <= m; i++) {
                res += s[i] * ans.a[i][b];
                res %= mod;
            }
            printf("%lld
", res);
        }
    }
    return 0;
}
原文地址:https://www.cnblogs.com/bpdwn-cnblogs/p/11249275.html