POJ 1195 Mobile phones(二维树状数组)

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了POJ 1195 Mobile phones(二维树状数组)相关的知识,希望对你有一定的参考价值。

题目链接:POJ 1195

题意:

  给出一个S*S的矩阵(行、列号从1开始),每个元素初始值为0,有两种操作:一种是第X行第Y列元素值加A;另一种是查询给定范围矩阵的所有元素之和(L<=X<=R,B<=Y<=T)。

分析:

  查询给定范围矩阵的所有元素之和是二维区间和,可以转换为二维前缀和求值。类比一维前缀和求法,二维区间和S(L, B, R, T) = S(1, 1, R, T) - S(1 ,1, L-1, T) - S(1, 1, R, B-1) + S(1, 1, L-1, B-1)。单点更新一个元素的值,修改二维前缀和,类比一维树状数组的更新操作,二维树状数组的更新操作(参考代码)。

总结:

  二维树状数组可以理解为:先固定X=i,把Y=1~S看作一维树状数组就比较容易理解,再X=1~S看作一维树状数组,这样组合成二维树状数组。如果还想不明白,可以想想二元积分是怎么做的。

代码实现:

#include <cstdio>
#include <cstring>
#include <algorithm>
#include <iostream>
#include <cmath>
using namespace std;
const int N = 1024 + 5;
int C[N][N], cmd, s, x, y, a, l, b, r, t;

int lowbit(int x)
{
    return x & (-x);
}
void add(int x, int y, int a)
{
    for (int i = x; i <= s; i += lowbit(i))
        for (int j = y; j <= s; j += lowbit(j))
            C[i][j] += a;
}
int sum(int x, int y)
{
    int ret = 0;
    for (int i = x; i; i -= lowbit(i))
        for (int j = y; j; j -= lowbit(j))
            ret += C[i][j];
    return ret;
}
int main()
{
    while (~scanf("%d", &cmd)) {
        if (cmd == 3) break;
        if (cmd == 0) {
            scanf("%d", &s);
            for (int i = 1; i <= s; i++)
                for (int j = 1; j <= s; j++)
                    C[i][j] = 0;
            continue;
        }
        if (cmd == 1) {
            scanf("%d%d%d", &x, &y, &a);
            x++, y++;
            add(x, y, a);
            continue;
        }
        if (cmd == 2) {
            scanf("%d%d%d%d", &l, &b, &r, &t);
            l++, b++, r++, t++;
            int ans = sum(r, t) - sum(l-1, t) - sum(r, b-1) + sum(l-1, b-1);
            printf("%d\n", ans);
        }
    }
    return 0;
}

  

以上是关于POJ 1195 Mobile phones(二维树状数组)的主要内容,如果未能解决你的问题,请参考以下文章

POJ 1195 Mobile phones (二维树状数组)

POJ1195 Mobile phones 二维线段树

POJ1195 Mobile phones 二维树状数组

poj1195 Mobile phones(二维树状数组)

POJ_1195 Mobile phones 二维树状数组

poj1195 Mobile phones 二维线段树入门