题意
一个N*M的方格,初始时每个格子有一个整数权值,接下来每次有2个操作:
改变一个格子的权值
求一个子矩阵中某个特定权值出现的个数
n,m<=300,Q<=5000,1<=c<=100
分析
话说哪个好事者把这题标签打成树套树的?
参照hzwer的题解。
对于每种颜色开一个二维树状数组水过。
时间复杂度\(O((nm+q)\log_2n\log_2m)\),空间复杂度\(O(nmc)\)。
代码
#include<bits/stdc++.h>
#define rg register
#define il inline
#define co const
template<class T>il T read(){
rg T data=0,w=1;
rg char ch=getchar();
while(!isdigit(ch)){
if(ch=='-') w=-1;
ch=getchar();
}
while(isdigit(ch))
data=data*10+ch-'0',ch=getchar();
return data*w;
}
template<class T>il T read(rg T&x){
return x=read<T>();
}
typedef long long ll;
int n,m,q;
int mp[301][301];
int t[101][301][301];
#define lowbit(x) (x&-x)
void update(int x,int y,int c,int val){
for(int i=x;i<=n;i+=lowbit(i))
for(int j=y;j<=m;j+=lowbit(j))
t[c][i][j]+=val;
}
int ask(int x,int y,int c){
int re=0;
for(int i=x;i;i-=lowbit(i))
for(int j=y;j;j-=lowbit(j))
re+=t[c][i][j];
return re;
}
int main(){
// freopen(".in","r",stdin);
// freopen(".out","w",stdout);
read(n),read(m);
for(int i=1;i<=n;++i)
for(int j=1;j<=m;++j)
update(i,j,read(mp[i][j]),1);
read(q);
while(q--){
int opt=read<int>();
if(opt==1){
int x=read<int>(),y=read<int>();
update(x,y,mp[x][y],-1);
update(x,y,read(mp[x][y]),1);
}
else{
int x1=read<int>(),x2=read<int>(),y1=read<int>(),y2=read<int>(),c=read<int>();
printf("%d\n",ask(x2,y2,c)+ask(x1-1,y1-1,c)-ask(x1-1,y2,c)-ask(x2,y1-1,c));
}
}
return 0;
}