( ext{Solution:})
开始有一种暴力的做法:对每一行维护 (100) 个树状数组对应 (100) 个颜色。查询枚举行来查询。
复杂度:(O(mcdot log ncdot q)) 过不去的样子。
考虑用二维树状数组,直接维护二维矩阵。修改与查询的复杂度都做到了 (O(log ncdot log m).)
于是最终复杂度可以做到 (O(qlog nlog m).)
注意树状数组实现上的细节:第二重循环要保证每次都是从 (y) 开始,所以要重新复制一个变量来做。而且两个维度的最大值也是不一样的,上界不同修改的时候要注意。
这题的树状数组显然没有 上帝造题的七分钟 那个树状数组难。这题算是入门版的二维树状数组。
维护矩阵同时维护一个颜色即可
#include<bits/stdc++.h>
using namespace std;
int tr[301][301][101],n,m,a[301][301],q;
inline int lowbit(int x){return x&(-x);}
void change(int x,int y,int c,int v){
for(;x<=n;x+=lowbit(x))
for(int i=y;i<=m;i+=lowbit(i))
tr[x][i][c]+=v;
}
int query(int x,int y,int c){
int res=0;
for(;x;x-=lowbit(x))
for(int i=y;i;i-=lowbit(i))
res+=tr[x][i][c];
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]);
change(i,j,a[i][j],1);
}
scanf("%d",&q);
for(;q;q--){
int opt;
scanf("%d",&opt);
if(opt==1){
int x,y,c;
scanf("%d%d%d",&x,&y,&c);
change(x,y,a[x][y],-1);
a[x][y]=c;
change(x,y,a[x][y],1);
}
else{
int ax,bx,ay,by,c;
scanf("%d%d%d%d%d",&ax,&bx,&ay,&by,&c);
int ans=query(bx,by,c)-query(ax-1,by,c)-query(bx,ay-1,c)+query(ax-1,ay-1,c);
printf("%d
",ans);
}
}
return 0;
}