「题解」洛谷 P4054 [JSOI2009]计数问题

题目

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
", 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;
}
原文地址:https://www.cnblogs.com/poi-bolg-poi/p/13599754.html