【二维树状数组】计数问题 @JSOI2009/upcexam5911
时间限制: 1 Sec 内存限制: 128 MB
题目描述
一个n*m的方格,初始时每个格子有一个整数权值。接下来每次有2种操作:
改变一个格子的权值;
求一个子矩阵中某种特定权值出现的个数。
输入
第一行有两个数n,m。
接下来n行,每行m个数,第i+1行第j个数表示格子(i,j)的初始权值。
接下来输入一个整数q。
接下来q行,每行描述一个操作。
操作1:“1 x y c”(不含双引号)。表示将格子(x,y)的权值改成c(1<=x<=n,1<=y<=m,1<=c<=100)。
操作2:“2 x1 x2 y1 y2 c”(不含双引号,x1<=x2,y1<=y2)。表示询问所有满足格子权值为c,且x1<=x<=x2,y1<=y<=y2的格子(x,y)的个数。
输出
对于每个操作2,按照在输入中出现的顺序,依次输出一行一个整数表示所求得的个数。
注意到 1<=c<=100
对每个c值建一个二维树状数组
修改时要更新两个树状数组,一个原来权值的,一个修改后的权值的
查询类似二维前缀和
#define FILE() freopen("../../in.txt","r",stdin)
#include <bits/stdc++.h>
using namespace std;
const int maxn = 305;
int C[105][maxn][maxn],mapp[maxn][maxn];//mapp记录每一位置当前权值
int n,m;
int lowbit(int t) {
return t&(-t);
}
void Modify(int val,int i,int j,int delta) {
for(int x=i; x<=n; x+=lowbit(x)) {
for(int y=j; y<=m; y+=lowbit(y)) {
C[val][x][y]+=delta;
}
}
}
int Sum(int val,int i,int j) {
int res = 0;
for(int x=i; x>0; x-=lowbit(x)) {
for(int y=j; y>0; y-=lowbit(y)) {
res += C[val][x][y];
}
}
return res;
}
int main() {
// FILE();
cin>>n>>m;
for(int i=1; i<=n; i++) {
for(int j=1; j<=m; j++) {
int val;
scanf("%d",&val);
mapp[i][j]=val;
Modify(val,i,j,1);
}
}
int q;
cin>>q;
for(int i=0; i<q; i++) {
int op,x,y,xx,yy,c;
scanf("%d",&op);
if(op==1) {
scanf("%d%d%d",&x,&y,&c);
Modify(mapp[x][y],x,y,-1);
Modify(c,x,y,1);
mapp[x][y] = c;
} else {
scanf("%d%d%d%d%d",&x,&xx,&y,&yy,&c);
printf("%d\n",Sum(c,xx,yy)-Sum(c,x-1,yy)-Sum(c,xx,y-1)+Sum(c,x-1,y-1));
}
}
return 0;
}