POJ--1195(二维树状数组单点修改+区间查询板子题)

地址:http://poj.org/problem?id=1195

题意:

0 s: s*s的初始为0的矩阵a[][]

1 X Y A:a[x][y]+A

2 L B R T:左上角a[L][B]到右下角a[R][T]的矩阵和。

解析:

二维数组数组板子,和一维基本类似:

void update(int x,int y,int z)
{
//    cout<<"?";
    for(int i=x;i<=n;i+=lowbit(i))
        for(int j=y;j<=n;j+=lowbit(j))
            c[i][j]+=z;
}
int getsum(int x,int y)
{
    int sum = 0 ;
    for(int i=x;i>=1;i-=lowbit(i))
        for(int j=y;j>=1;j-=lowbit(j))
            sum+=c[i][j];
    return sum;
}

求和,画图即可理解,左上角被减去了两次。

坐标都要记得+1,因为树状数组i=0时无效

#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
const int maxn=1200;
int c[maxn][maxn];
int x,n;
int lowbit(int x)
{
    return x&(-x);
}
void update(int x,int y,int z)
{
//    cout<<"?";
    for(int i=x;i<=n;i+=lowbit(i))
        for(int j=y;j<=n;j+=lowbit(j))
            c[i][j]+=z;
}
int getsum(int x,int y)
{
    int sum = 0 ;
    for(int i=x;i>=1;i-=lowbit(i))
        for(int j=y;j>=1;j-=lowbit(j))
            sum+=c[i][j];
    return sum;
}
int getall(int x1,int y1,int x2,int y2)
{
    return getsum(x2,y2)-getsum(x1-1,y2)-getsum(x2,y1-1)+getsum(x1-1,y1-1);
}
int main()
{
    while(scanf("%d",&x)!=EOF)
    {
        if(x==0)
        {
            scanf("%d",&n);
            memset(c,0,sizeof(c));
        }
        else if(x==1)
        {
            int i,j,y;
            scanf("%d%d%d",&i,&j,&y);        
            update(i+1,j+1,y);
        }
        else if(x==2)
        {
            int x1,y1,x2,y2;
            scanf("%d%d%d%d",&x1,&y1,&x2,&y2);
            cout<<getall(x1+1,y1+1,x2+1,y2+1)<<endl;        
        }
    }
}
原文地址:https://www.cnblogs.com/liyexin/p/12993462.html