一本通1540打鼹鼠_二维树状数组

1540:打鼹鼠_二维树状数组

时间限制: 1000 ms         内存限制: 524288 KB

【题目描述】

这是一道模板题。

给出一个 n×m 的零矩阵 A,你需要完成如下操作:

1 x y k:表示元素 Ax,y自增 k

2 a b c d:表示询问左上角为 (a,b),右下角为 (c,d) 的子矩阵内所有数的和。

【输入】

输入的第一行有两个正整数 n,m

接下来若干行,每行一个操作,直到文件结束。

【输出】

对于每个 2 操作,输出一个整数,表示对于这个操作的回答。

【输入样例】

2 2
1 1 1 3
1 2 2 4
2 1 1 2 2

【输出样例】

7

【提示】

数据范围与提示:

对于 10% 的数据,n=1

对于另 10% 的数据,m=1

对于全部数据,1n,m2^12,1x,a,cn,1y,b,dm,k∣≤10^5,保证操作数目不超过 3×10^5 ,且询问的子矩阵存在。

如题所言这是一道二维BIT的模板题

#include <bits/stdc++.h>
using namespace std;
const int N=5005;
int n,m;
struct BIT
{
    long long S[N][N];
    #define lowbit(x) ((x)&(-x))
    inline void Ins(int x,int y,int Tag)
    {
        int ly=y;
        while(x<=n)
        {
            while(y<=m)
            {
                S[x][y]+=Tag;
                y+=lowbit(y);
            }
            x+=lowbit(x);
            y=ly;
        }
        return;
    }
    inline long long Que(int x,int y)
    {
        long long Sum=0;
        int ly=y;
        while(x>0)
        {
            while(y>0)
            {
                Sum+=S[x][y];
                y-=lowbit(y);
            }
            x-=lowbit(x);
            y=ly;
        }
        return Sum;
    }
}T;
int main()
{
    int i;
    scanf("%d%d",&n,&m);
    int opt;
    while(~scanf("%d",&opt))
    {
        switch(opt)
        {
            case 1:
                int x,y,k;
                scanf("%d%d%d",&x,&y,&k);
                T.Ins(x,y,k);
                break;
            case 2:
                int a,b,c,d;
                scanf("%d%d%d%d",&a,&b,&c,&d);
                printf("%lld
",T.Que(c,d)-T.Que(a-1,d)-T.Que(c,b-1)+T.Que(a-1,b-1));
                break;
        }
    }
    return 0;
}
View Code
原文地址:https://www.cnblogs.com/gaojunonly1/p/10350036.html