NOIP模拟 Matrix 矩阵运算

题目描述

给出两个 N×N 的矩阵 A、B,矩阵每行每列标号 0~N-1 。
定义这两个矩阵的乘积 AB 为

ABi,j=k=0n1Ai,jBi,j

现在要在这两个矩阵上依次进行 Q 次修改操作,两种操作描述如下:
A i j K ,将 Ai,j 的值修改为 K 。
B i j K ,将 Bi,j 的值修改为 K 。
在每一次修改操作进行后,输出矩阵 AB(这两个矩阵的乘积矩阵)中每个位置元素的权值之和。

输入格式

第一行,一个正整数 N ,表示矩阵的大小。
接下来 N 行,每行 N 个整数,描述矩阵 A 。
接下来 N 行,每行 N 个整数,描述矩阵 B 。
接下来一行,一个正整数 Q ,表示操作次数。
接下来 Q 行,每行描述一个操作,格式如题面所示。

输出格式

输出 Q 行,每行一个整数,表示这次操作完成后的答案。

样例数据 1

输入  [复制]

2
1 2
3 4
4 3
2 1
3
A 1 1 2
B 0 1 3
A 0 0 10

输出

40
40
103
备注
【数据规模与约定】
对于 10% 的数据,N = 1。
对于 30% 的数据,N,Q≤10。
对于 80% 的数据,1≤N≤100,|Ai,j|,|Bi,j|≤10。
对于 100% 的数据,1≤N≤1000,1≤Q≤105,|Aij|,|Bi,j|≤1000。

解题思路

可以发现,若修改的是A i,j ,因为其只和B j,k(0kn1) 相乘,若修改的是B i,j ,因为其只和A k,i(0kn1) 相乘,所以我们可以预处理B的每行之和,A的每列之和,就可以 O1 修改总和。

同理,最开始是可以用A i,j 去乘B的第j行之和, On2 算出初始和。

#include<iostream>
#include<cstdio>
#include<cstring>
#include<string>
#include<algorithm>
#include<cmath>
#include<queue>
#include<vector>
using namespace std;

int getint()
{
    int i=0,f=1;char c;
    for(c=getchar();(c>'9'||c<'0')&&c!='-';c=getchar());
    if(c=='-')c=getchar(),f=-1;
    for(;c>='0'&&c<='9';c=getchar())i=(i<<3)+(i<<1)+c-'0';
    return i*f;
}

const int N=1005;
int n,m;
long long A[N][N],B[N][N],Asumy[N],Bsumx[N];
long long ans;

int main()
{
    //freopen("matrix.in","r",stdin);
    //freopen("matrix.out","w",stdout);
    n=getint();
    for(int i=0;i<n;i++)
        for(int j=0;j<n;j++)
        {
            A[i][j]=getint();
            Asumy[j]+=A[i][j];
        }
    for(int i=0;i<n;i++)
        for(int j=0;j<n;j++)
        {
            B[i][j]=getint();
            Bsumx[i]+=B[i][j];
            ans+=(long long)Asumy[i]*B[i][j];
        }
    m=getint();
    int x,y,val,delta;char c;
    while(m--)
    {
        for(c=getchar();c!='A'&&c!='B';c=getchar());
        x=getint(),y=getint(),val=getint();
        if(c=='A')
        {
            delta=val-A[x][y];
            A[x][y]=val;
            Asumy[y]+=delta;
            ans+=(long long)delta*Bsumx[y];
            cout<<ans<<'\n';
            continue;
        }
        if(c=='B')
        {
            delta=val-B[x][y];
            B[x][y]=val;
            Bsumx[x]+=delta;
            ans+=(long long)delta*Asumy[x];
            cout<<ans<<'\n';
            continue;
        }
    }
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值