NOIP模拟 Matrix 矩阵运算

时间:2022-12-17 10:16:49

题目描述

给出两个 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;
}