E. MAZE (Line Tree + dp)

Keywords: Windows iOS

Question meaning: Give you a matrix of n*m. You can only go left to right. There are two kinds of operations q times to ask: one is to turn a unit over (that is to say, walk into non-walk into walk), the other is to ask how many options are there from (1, x) to (n, y).

Thought: Topic n is 1e5 and M is only 10. We can consider maintaining an m*m matrix on the online segment tree. When simulating matrix multiplication, it is equivalent to calculating the number of alternatives (simulated manually by ourselves). Modification operation is equivalent to single point updating, and then reconstructing the matrix.

#include <bits/stdc++.h>
using namespace std;
const int N = 5e4+7;
const int inf = 0x3f3f3f3f;
typedef long long ll;
const ll mod = 1e9+7;
ll a[N][12];
int n,m,q;
struct matrix{
    int l,r;
    ll ma[12][12];
};
matrix t[N<<2];
void pushup(int p){
    memset(t[p].ma,0,sizeof(t[p].ma));
    for(int i=1;i<=m;i++)
        for(int j=1;j<=m;j++)
            for(int k=1;k<=m;k++){
                t[p].ma[i][j]=(t[p].ma[i][j]+((t[p<<1].ma[i][k]%mod)*(t[p<<1|1].ma[k][j]%mod))%mod)%mod;   
            }
}
void work(int p,int l){
    memset(t[p].ma,0,sizeof(t[p].ma));
    for(int i=1;i<=m;i++){
        int pos=i;
        while(pos>=1&&a[l][pos]==0){
            t[p].ma[i][pos]=1;
            pos--;
        }
        pos=i;
        while(pos<=m&&a[l][pos]==0){
            t[p].ma[i][pos]=1;
            pos++;
        }
    }
}
void build(int p,int l,int r){
    t[p].l=l; t[p].r=r;
    if(l==r){
        work(p,l);
        return ;
    }
    int mid=(l+r)>>1;
    build(p<<1,l,mid);
    build(p<<1|1,mid+1,r);
    pushup(p);
}
void update(int p,int x){
    if(t[p].l==t[p].r){
        work(p,t[p].l);
        return ;
    }
    int mid=(t[p].l+t[p].r)>>1;
    if(x<=mid) update(p<<1,x);
    else update(p<<1|1,x);
    pushup(p);
}
int main(){
    ios::sync_with_stdio(false);
    cin.tie(0); cout.tie(0);
    cin>>n>>m>>q;
    for(int i=1;i<=n;i++){
        for(int j=1;j<=m;j++){
            char b; cin>>b;
            a[i][j]=(b!='0');
        }
    }   
    build(1,1,n);
    for(int i=1;i<=q;i++){
        int z,x,y; cin>>z>>x>>y;
        if(z==1){
            a[x][y]^=1;
            update(1,x);
        }else{
            cout<<t[1].ma[x][y]<<"\n";
        }
    }
    return 0;
}

Posted by castis on Tue, 30 Jul 2019 21:19:53 -0700