二维树状数组求前缀和裸题
不能再裸啦!
具体过程
对于每个修改,暴力在树状数组上修改就好,对于询问,根据二维前缀和的性质{i,k}{j,l}的前缀和 = s [ j ] [ l ] − s [ i − 1 ] [ l ] − s [ j ] [ k − 1 ] + s [ i − 1 ] [ k − 1 ] =s[j][l]-s[i-1][l]-s[j][k-1]+s[i-1][k-1] =s[j][l]−s[i−1][l]−s[j][k−1]+s[i−1][k−1],然后用树状数组优化一下就好了
代码
//By AcerMo
#include<cmath>
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#define lowbit(x) x&(-x)
using namespace std;
int n,m,q;
int a[305][305],s[305][305][105];
inline void read(int &x)
{
x=0;char ch=getchar();
while (!isdigit(ch)) ch=getchar();
while (isdigit(ch)) x=x*10+ch-'0',ch=getchar();
return ;
}
inline void add(int x,int y,int z,int v)
{
for (int i=x;i<=n;i+=lowbit(i))
for (int k=y;k<=m;k+=lowbit(k))
s[i][k][z]+=v;
return ;
}
inline int sum(int x,int y,int z)
{
int su=0;
for (int i=x;i;i-=lowbit(i))
for (int k=y;k;k-=lowbit(k))
su+=s[i][k][z];
return su;
}
signed main()
{
read(n);read(m);
for (int i=1;i<=n;i++)
for (int k=1;k<=m;k++)
read(a[i][k]),add(i,k,a[i][k],1);
read(q);
int x,y,z,f,g;
while (q--)
{
int fl;read(fl);
read(x);read(y);read(z);
if (fl==1)
add(x,y,a[x][y],-1),add(x,y,z,1),a[x][y]=z;
else
{
read(f);read(g);
int a1=sum(y,f,g);
int a2=sum(y,z-1,g);
int a3=sum(x-1,f,g);
int a4=sum(x-1,z-1,g);
printf("%d\n",a1-a2-a3+a4);
}
}
return 0;
}