「题解」洛谷 P4054 [JSOI2009]计数问题
题目
简化题意
给你一个矩阵,需要支持单点修改以及询问子矩阵中某数出现的次数。
思路
二维树状数组。
因为值 小于等于 \(100\) 所以开 \(100\) 个二维树状数组分别维护每个值。
Code
#include <cstdio>
#include <cstring>
#include <string>
#include <iostream>
#include <algorithm>
int n, m, q, map[301][301];
struct BIT {
int c[301][301];
BIT() { memset(c, 0, sizeof c); }
int lowbit(int x) { return x & (-x); }
void add(int x, int y, int k) {
for (int i = x; i <= n; i += lowbit(i)) {
for (int j = y; j <= m; j += lowbit(j)) {
c[i][j] += k;
}
}
}
int sum(int x, int y) {
int ans = 0;
for (int i = x; i > 0; i -= lowbit(i)) {
for (int j = y; j > 0; j -= lowbit(j)) {
ans += c[i][j];
}
}
return ans;
}
}b[101];
int main() {
scanf("%d %d", &n, &m);
for (int i = 1; i <= n; ++i) {
for (int j = 1; j <= m; ++j) {
scanf("%d", &map[i][j]);
b[map[i][j]].add(i, j, 1);
}
}
scanf("%d", &q);
for (int i = 1, opt, x, y, k; i <= q; ++i) {
scanf("%d %d", &opt, &x);
if (opt == 1) {
scanf("%d %d", &y, &k);
b[map[x][y]].add(x, y, -1);
b[k].add(x, y, 1);
map[x][y] = k;
}
else {
int x2, y2;
scanf("%d %d %d %d", &x2, &y, &y2, &k);
printf("%d\n", b[k].sum(x2, y2) - b[k].sum(x2, y - 1) - b[k].sum(x - 1, y2) + b[k].sum(x - 1, y - 1));
}
}
return 0;
}