一个N*M的方格,初始时每个格子有一个整数权值,接下来每次有2个操作:
改变一个格子的权值
求一个子矩阵中某个特定权值出现的个数
这道题是一道二维树状数组裸题,但这个权值怎么搞呢?其实非常简单,多开一维,变成三维数组,因为权值的范围很小,这一点应当注意。那这道题就很简单了,询问的时候就只要把一个矩阵切来切去就可以得到你想要的矩阵了。
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<cmath>
#include<algorithm>
using namespace std;
int n,m,a[310][310];
int s[110][310][310];
int lowbit(int x){return x&-x;}
void add(int x,int y,int w,int d)
{
for(int i=x;i<=n;i+=lowbit(i))
{
for(int j=y;j<=m;j+=lowbit(j))
{
s[w][i][j]+=d;
}
}
}
int getsum(int x,int y,int w)
{
int ans=0;
for(int i=x;i>=1;i-=lowbit(i))
{
for(int j=y;j>=1;j-=lowbit(j))
{
ans+=s[w][i][j];
}
}
return ans;
}
int main()
{
scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++)
{
for(int j=1;j<=m;j++)
{
int x;
scanf("%d",&x);
a[i][j]=x;
add(i,j,x,1);
}
}
int t;
scanf("%d",&t);
while(t--)
{
int kd,sx,sy,ex,ey,c;
scanf("%d%d%d",&kd,&sx,&ex);
if(kd==1)
{
scanf("%d",&c);
add(sx,ex,a[sx][ex],-1);
a[sx][ex]=c;
add(sx,ex,a[sx][ex],1);
}
else
{
scanf("%d%d%d",&sy,&ey,&c);
printf("%d\n",getsum(ex,ey,c)-getsum(ex,sy-1,c)-getsum(sx-1,ey,c)+getsum(sx-1,sy-1,c));
}
}
return 0;
}