题意
一个$n \times m$的方格,初始时每个格子有一个整数权值
接下来每次有$2$种操作
- 改变一个格子的权值
- 求一个子矩阵中某种特定权值出现的个数
数据范围:$n,m \le 300,1 \le c \le 100$
题解
$n,m,c$较小,对于每个$c$开一个二维树状数组维护
代码:
#include<iostream>
#include<cstdio>
using namespace std;
const int N=300+10;
const int C=100+10;
int n,m,q,op,x1,x2,y1,y2,c;
int a[N][N];
int T[C][N][N];
inline int lowbit(int x){
return x&-x;
}
inline void update(int u,int x,int y,int k){
for(;x<=n;x+=lowbit(x))
for(int i=y;i<=m;i+=lowbit(i))
T[u][x][i]+=k;
}
inline int query(int u,int x,int y){
int res=0;
for(;x;x-=lowbit(x))
for(int i=y;i;i-=lowbit(i))
res+=T[u][x][i];
return res;
}
int main(){
scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++)
for(int j=1;j<=m;j++){
scanf("%d",&a[i][j]);
update(a[i][j],i,j,1);
}
scanf("%d",&q);
for(;q--;){
scanf("%d",&op);
if(op==1){
scanf("%d%d%d",&x1,&y1,&c);
update(a[x1][y1],x1,y1,-1);
a[x1][y1]=c;
update(a[x1][y1],x1,y1,1);
}
else{
scanf("%d%d%d%d%d",&x1,&x2,&y1,&y2,&c);
printf("%d\n",query(c,x2,y2)-query(c,x1-1,y2)-query(c,x2,y1-1)+query(c,x1-1,y1-1));
}
}
return 0;
}