BZOJ-1452 [JSOI2009]Count(二维树状数组)
题目描述
给一个 \(n\times m\) 的矩阵和 \(q\) 次操作,初始时每个格子有一个数字。有 \(2\) 种操作:
操作 \(1\):1 x y c
,将格子 \((x,y)\) 的数字改成 \(c\)。
操作 \(2\):2 x1 x2 y1 y2 c
,询问所有满足格子数字为 \(c\),且 \(x1\leq x\leq x2,y1\leq y\leq y2\) 的格子\((x,y)\) 的个数。
数据范围:\(n,m\leq 300,q\leq 5000.1\leq c\leq 100\)。
分析
\(c\) 的值域很小,最大只有 \(100\),用 \(100\) 个二维树状数组存储每个数在矩阵中出现的次数。
对于操作 \(1\),把 \((x,y)\) 从 \(a\) 修改为 \(c\),值 \(a\) 的树状数组对应位置的出现次数 \(-1\),值 \(b\) 的树状数组对应位置的出现次数 \(+1\)。
对于操作 \(2\),直接输出出现次数。
代码
#include<bits/stdc++.h>
using namespace std;
const int N=310;
int n,m;
int c[N][N][N];
int a[N][N];
int lowbit(int x)
{
return x&-x;
}
void add(int val,int x,int y,int z)
{
for(int i=x;i<=n;i=i+lowbit(i))
for(int j=y;j<=m;j=j+lowbit(j))
c[val][i][j]+=z;
}
int query(int val,int x,int y)
{
int ans=0;
for(int i=x;i;i=i-lowbit(i))
for(int j=y;j;j=j-lowbit(j))
ans=ans+c[val][i][j];
return ans;
}
int main()
{
cin>>n>>m;
for(int i=1;i<=n;i++)
{
for(int j=1;j<=m;j++)
{
scanf("%d",&a[i][j]);
add(a[i][j],i,j,1);
}
}
int q;
cin>>q;
while(q--)
{
int op;
scanf("%d",&op);
if(op==1)
{
int x,y,c;
scanf("%d %d %d",&x,&y,&c);
add(a[x][y],x,y,-1);
a[x][y]=c;
add(c,x,y,1);
}
else
{
int X1,X2,Y1,Y2,c;
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;
}
posted on 2020-12-13 12:44 DestinHistoire 阅读(76) 评论(0) 编辑 收藏 举报