二维树状数组 :单点修改,区间查询(模板)

题目传送门

给你一个n*m的邻接矩阵,完成以下两个操作。

"1 x y k":表示元素 Ax,y 自增 k;
"2 a b c d":表示询问左上角为 (a,b),右下角为 (c,d) 的子矩阵内所有数的和。

input

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

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

output

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

example

Input
2 2
1 1 1 3
1 2 2 4
2 1 1 2 2
Output
7

note

1≤n,m≤2^12,1≤x,a,c≤n,1≤y,b,d≤m,|k|105,保证操作数目不超过 3×10^5,且询问的子矩阵存在。

基本操作和一维树状数组差不多,求和的时候注意下二维前缀和的求法就可以。

#include
using namespace std;
typedef long long ll;
const int N=5e3+5;
const int mod=1e9+7;
const int INF=0x7fffffff;
const ll LLINF=0x7fffffffffffffff;
const double EPS=1e-10;
#define IOS ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
#define pb push_back
#define pii pair
#define pll pair
#define debug cout<<"debug"<
#define ls p<<1
#define rs p<<1|1
#define int long long
int c[N][N];
int lowbit(int x)
{
    return x&-x;
}
int n,m;
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 s=0;
    for(int i=x;i;i-=lowbit(i))
    {
        for(int j=y;j;j-=lowbit(j))
        {
            s+=c[i][j];
        }
    }
    return s;
}
signed main()
{
    IOS;
    //freopen("","r",stdin);
    //freopen("","w",stdout);
    scanf("%lld%lld",&n,&m);
    int oo,x,y,z,w;
    while(scanf("%lld",&oo)!=EOF)
    {
        if(oo==1)
        {
            scanf("%lld%lld%lld",&x,&y,&z);
            add(x,y,z);
        }
        else
        {
            scanf("%lld%lld%lld%lld",&x,&y,&z,&w);
            printf("%lld\n",sum(z,w)-sum(x-1,w)-sum(z,y-1)+sum(x-1,y-1));
        }
    }
}

你可能感兴趣的:(树状数组)