Description
Input
Output
Sample Input
3 3
1 2 3
3 2 1
2 1 3
3
2 1 2 1 2 1
1 2 3 2
2 2 3 2 3 2
Sample Output
1
2
题解
二维树状数组
s[p][i][j]表示,以(1,1)为左上端点到(i,j)为右下端点的矩阵,共有多少个颜色p
然后按照一维数组转移就好了
有个小错误要提示一下,不能把矩阵展开来做,就是不能s[p][i]
因为这样的话要多一个for去枚举每一行,直接TLE。。因为这个挂了一会
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<algorithm>
#include<cmath>
using namespace std;
int s[110][310][310];
int map[310][310];
int n,m;
int lowbit(int x){return x&-x;}
void change(int p,int x,int y,int k)
{
for(int i=x;i<=n;i+=lowbit(i))
for(int j=y;j<=n;j+=lowbit(j))
s[p][i][j]+=k;
}
int findsum(int p,int x,int y)
{
int ans=0;
for(int i=x;i>=1;i-=lowbit(i))
for(int j=y;j>=1;j-=lowbit(j))
ans+=s[p][i][j];
return ans;
}
int q;
int main()
{
memset(s,0,sizeof(s));
scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++)
{
for(int j=1;j<=m;j++)
{
scanf("%d",&map[i][j]);
change(map[i][j],i,j,1);
}
}
scanf("%d",&q);
while(q--)
{
int op;
scanf("%d",&op);
if(op==1)
{
int x,y,c;
scanf("%d%d%d",&x,&y,&c);
change(map[x][y],x,y,-1);
map[x][y]=c;
change(map[x][y],x,y,1);
}
else
{
int x1,x2,y1,y2,c;
scanf("%d%d%d%d%d",&x1,&x2,&y1,&y2,&c);
int ans=0;
ans+=findsum(c,x2,y2);
ans-=findsum(c,x1-1,y2);ans-=findsum(c,x2,y1-1);
ans+=findsum(c,x1-1,y1-1);
printf("%d\n",ans);
}
}
return 0;
}