GYM100376E.LinearMapReduce(线段树维护矩阵乘法)

题意:

给出一个初始矩阵,和n个不同的中间矩阵,每次询问初始矩阵从第a个矩阵乘到第b个矩阵的答案。

题解:

用线段树维护矩阵乘法,矩阵乘法不存在交换律,只存在结合律,这回刻到DNA里了。(这里询问包含两个方向,所以要开两颗线段树维护)

#include<bits/stdc++.h>
using namespace std;
const int maxn=1e5+100;
const int mod=1e9+7;
typedef long long ll;
struct matrix {
    ll m[3][3];
};
void ccpy (matrix &x,matrix y) {
    for (int i=1;i<=2;i++) for (int j=1;j<=2;j++) x.m[i][j]=y.m[i][j];
}
void mul (matrix &ans,matrix a,matrix b) {
    for (int i=1;i<=2;i++) for (int j=1;j<=2;j++) ans.m[i][j]=0;
    for (int k=1;k<=2;k++) {
        for (int i=1;i<=2;i++) {
            for (int j=1;j<=2;j++) {
                ans.m[i][j]+=a.m[i][k]*b.m[k][j]%mod;
                ans.m[i][j]%=mod;
            }
        }
    }
}
struct node {
    int l,r;
    matrix sum;
}segTree[maxn<<2][2];
ll K,V;
int n,q;
ll a[maxn][3][3];
void build (int i,int l,int r,int f) {
    segTree[i][f].l=l;
    segTree[i][f].r=r;
    if (l==r) {
        segTree[i][f].sum.m[1][1]=a[l][1][1];
        segTree[i][f].sum.m[2][1]=a[l][1][2];
        segTree[i][f].sum.m[1][2]=a[l][2][1];
        segTree[i][f].sum.m[2][2]=a[l][2][2];
        return;
    }
    int mid=(l+r)>>1;
    build(i<<1,l,mid,f);
    build(i<<1|1,mid+1,r,f);
    if (f==0)
        mul(segTree[i][f].sum,segTree[i<<1][f].sum,segTree[i<<1|1][f].sum);
    else
        mul(segTree[i][f].sum,segTree[i<<1|1][f].sum,segTree[i<<1][f].sum);
}
matrix query (int i,int l,int r,int f) {
    //区间查询矩阵和 
    if (segTree[i][f].l>=l&&segTree[i][f].r<=r) {
        return segTree[i][f].sum;
    }
    matrix ans;
    int mid=(segTree[i][f].l+segTree[i][f].r)>>1;
    if (r<=mid) return query(i<<1,l,r,f);
    else if (l>mid) return query(i<<1|1,l,r,f);
    else {
        matrix ans;
        if (f==0)
            mul(ans,query(i<<1,l,r,f),query(i<<1|1,l,r,f));
        else
            mul(ans,query(i<<1|1,l,r,f),query(i<<1,l,r,f));
        return ans;
    }
    return ans;
}
int main () {
    scanf("%d%d",&n,&q);
    for (int i=1;i<=n;i++) for (int j=1;j<=2;j++) for (int k=1;k<=2;k++) scanf("%lld",&a[i][j][k]);
    build(1,1,n,0);
    build(1,1,n,1);
    while (q--) {
        ll k,v,a,b;
        scanf("%lld%lld%lld%lld",&k,&v,&a,&b);
        matrix ans;
        ans.m[1][1]=k;
        ans.m[2][1]=0;
        ans.m[1][2]=v;
        ans.m[2][2]=0;
        matrix q1;
        if (a<b)
            q1=query(1,a,b,0);
        else
            q1=query(1,b,a,1);
        //printf("%lld %lld\n%lld %lld\n\n",q1.m[1][1],q1.m[1][2],q1.m[2][1],q1.m[2][2]);
        
        //printf("%lld %lld\n%lld %lld\n\n",ans.m[1][1],ans.m[1][2],ans.m[2][1],ans.m[2][2]);
        matrix tt;
        mul(tt,ans,q1);

        printf("%lld %lld\n",tt.m[1][1],tt.m[1][2]);
    }
}

 

posted @ 2021-03-27 10:21  zlc0405  阅读(74)  评论(0编辑  收藏  举报