二维树状数组板子
貌似还是紫掉蓝
题目描述
一个 (left(n imes m
ight)) 的方格,初始时每个格子有一个整数权值。接下来每次有2种操作:
改变一个格子的权值;
求一个子矩阵中某种特定权值出现的个数。
输入格式
第一行有两个数 (N),(M)。
接下来 (N) 行,每行 (M) 个数,第 (i+1) 行第 (j) 个数表示格子 (left(i,j
ight)) 的初始权值。
接下来输入一个整数 (Q)。
之后 (Q) 行,每行描述一个操作。
操作 (1):“(1quad xquad yquad c)”(不含双引号)。表示将格子 (left(x,y
ight)) 的权值改成 (c) (left( 1le xle n,1le yle m,1le cle 100
ight))。
操作 (2):“(2quad x_1quad x_2quad y_1quad y_2quad c)”(不含双引号,(x_1le x_2,y_1le y_2))。表示询问所有满足格子颜色为 (c),且 (x_1le xle x_2), (y_1le yle y_2)的格子(left(x,y
ight))的个数。
输出格式
对于每个操作 (2),按照在输入中出现的顺序,依次输出一行一个整数表示所求得的个数。
注意毒瘤输入
最后那里答案统计会产生重叠, 需要删去重叠部分
不开快读会 (WA)
代码:
# include <iostream>
# include <cstdio>
# define MAXN 305
using namespace std;
int c[MAXN][MAXN][101], a[MAXN][MAXN]; // c[x][y][col] 统计 col 出现的次数
int n, m;
int read(){
char ch = getchar();
int x = 0;
while(ch < '0' || ch > '9') ch = getchar();
while(ch >='0' && ch <='9'){
x = x * 10 + ch - '0';
ch = getchar();
}
return x;
}
int Lowbit(int x){
return x&(-x);
}
void Update(int x, int y, int col, int val){
a[x][y] = col;
for(int i = x; i <= n; i += Lowbit(i)){
for(int j = y; j <= m; j += Lowbit(j)){
c[i][j][col] += val;
}
}
}
long long Getsum(int x, int y, int col){
long long ans = 0;
for(int i = x; i; i -= Lowbit(i)){
for(int j = y; j; j -= Lowbit(j)){
ans += c[i][j][col];
}
}
return ans;
}
int main(){
int q, opt, xa, ya, xb, yb, tmp;
n = read(), m =read();
for(int i = 1; i <= n; i++){
for(int j = 1; j <= m; j++){
tmp = read();
Update(i, j, tmp, 1);
}
}
q = read();
for(int i = 1; i <= q; i++){
opt = read();
if(opt == 1){
xa = read(), ya = read(), tmp = read();
Update(xa, ya, a[xa][ya], -1);
Update(xa, ya, tmp, 1);
}
else{
xa = read(), xb = read(), ya = read(), yb = read(), tmp =read();
cout<<Getsum(xb, yb, tmp) + Getsum(xa-1, ya-1, tmp) - Getsum(xa-1, yb, tmp) - Getsum(xb, ya-1, tmp) <<endl;
}
}
return 0;
}