题目链接: P4054 [JSOI2009]计数问题
题目大意: 给出一个 n ∗ m ( 1 ≤ n , m ≤ 300 ) n*m(1\leq n,m\leq 300) n∗m(1≤n,m≤300)的矩阵,每次可以修改一个位置的值,或者查询一个子矩阵内值等于 c c c的数的个数,其中矩阵中数字 x x x满足 1 ≤ x ≤ 100 1\leq x \leq 100 1≤x≤100
题目分析: 考虑到矩阵内数字的值域很小,我们可以将每个数字都分别建一个二维树状数组,然后就是一道二维树状数组的裸题了。
题目代码:
#include<stdio.h>
#include<algorithm>
#include<string.h>
using namespace std;
int n,m,q,Bit[305][305][105],map[305][305];
int lowbit(int x){
return x&-x;
}
void Modify(int x,int y,int v,int c){
for(int i=x;i<=n;i+=lowbit(i))
for(int j=y;j<=m;j+=lowbit(j))
Bit[i][j][c]+=v;
}
int Sum(int x,int y,int c){
int ret=0;
for(int i=x;i>=1;i-=lowbit(i))
for(int j=y;j>=1;j-=lowbit(j))
ret+=Bit[i][j][c];
return ret;
}
int main()
{
scanf("%d %d",&n,&m);
for(int i=1;i<=n;i++)
for(int j=1;j<=m;j++){
scanf("%d",&map[i][j]);
Modify(i,j,1,map[i][j]);
}
scanf("%d",&q);
while(q--){
int op;
scanf("%d",&op);
if(op==1){
int x,y,c;
scanf("%d %d %d",&x,&y,&c);
Modify(x,y,1,c);
Modify(x,y,-1,map[x][y]);
map[x][y]=c;
}
else{
int x1,x2,y1,y2,c;
scanf("%d %d %d %d %d",&x1,&x2,&y1,&y2,&c);
int ans=Sum(x2,y2,c)-Sum(x2,y1-1,c)-Sum(x1-1,y2,c)+Sum(x1-1,y1-1,c);
printf("%d\n",ans);
}
}
return 0;
}