模板 - 数据结构 - 二维树状数组

二维树状数组涉及到两种基本操作,修改矩阵中的一个点,查询子矩阵的和。

首先是修改点:

void update(int x,int y,int z)
{
    for(int i=x;i<=n;i+=lowbit(i))
    for(int j=y;j<=m;j+=lowbit(j))
        c[i][j]+=z;
}

然后是查询前缀和:

int get_sum(int x,int y)
{
    int ret=0;
    for(int i=x;i>=1;i-=lowbit(i))
    for(int j=y;j>=1;j-=lowbit(j))
        ret+=c[i][j];
    return ret;
}

那么由容斥原理:

inline int query(int x1,int y1,int x2,int y2){
    return get_sum(x2,y2)-get_sum(x1-1,y2)-get_sum(x2,y1-1)+get_sum(x1-1,y1-1);
}

 

 

区间修改就麻烦一点:

方法1:

#include<iostream>
using namespace std;
const int maxn=1005;
const int maxm=1005;
int n,m;
int q;
int a[maxn][maxm];
int c[maxn][maxm];
int lowbit(int x)
{
    return x&(-x);
}
void update(int x,int y,int z)
{
    for(int i=x;i<=n;i+=lowbit(i))
    for(int j=y;j<=m;j+=lowbit(j))
        c[i][j]+=z;
}

int sum(int x,int y)
{
    int ret=0;
    for(int i=x;i>=1;i-=lowbit(i))
    for(int j=y;j>=1;j-=lowbit(j))
        ret+=c[i][j];
    return ret;
}
int main()
{
    cin>>n>>m;
    cin>>q;
    while(q--)
    {
        int x;
        cin>>x;
        if(x==1)
        {
            int x1,y1,x2,y2,w;
            cin>>x1>>y1>>x2>>y2>>w;
            update(x1,y1,w);
            update(x2+1,y2+1,w);
            update(x2+1,y1,-w);
            update(x1,y2+1,-w);
        }
        if(x==2)
        {
            int x,y;
            cin>>x>>y;
            cout<<sum(x,y)<<endl;
        }
    }
    return 0;
}

方法2:

#include<iostream>
using namespace std;
const int maxn=1005;
const int maxm=1005;
int n,m;
int q;
int a[maxn][maxm];
int c1[maxn][maxm];
int c2[maxn][maxm];
int c3[maxn][maxm];
int c4[maxn][maxm];
int lowbit(int x)
{
    return x&(-x);
}
void update(int c[][maxm],int x,int y,int z)
{
    for(int i=x;i<=n;i+=lowbit(i))
    for(int j=y;j<=m;j+=lowbit(j))
        c[i][j]+=z;
}

int sum(int c[][maxm],int x,int y)
{
    int ret=0;
    for(int i=x;i>=1;i-=lowbit(i))
    for(int j=y;j>=1;j-=lowbit(j))
        ret+=c[i][j];
    return ret;
}

int get(int x,int y)
{
    return sum(c1,x,y)*(x+1)*(y+1)-sum(c2,x,y)*(y+1)-(x+1)*sum(c3,x,y)+sum(c4,x,y);
}
int main()
{
    cin>>n>>m;
    cin>>q;
    while(q--)
    {
        int x;
        cin>>x;
        if(x==1)
        {
            int x1,y1,x2,y2,w;
            cin>>x1>>y1>>x2>>y2>>w;
            update(c1,x1,y1,w),update(c1,x1,y2+1,-w);
            update(c1,x2+1,y1,-w),update(c1,x2+1,y2+1,w);
        
            update(c2,x1,y1,w*x1),update(c2,x2+1,y1,-w*(x2+1));
            update(c2,x1,y2+1,-w*x1),update(c2,x2+1,y2+1,w*(x2+1));
        
            update(c3,x1,y1,w*y1),update(c3,x2+1,y1,-w*y1);
            update(c3,x1,y2+1,-w*(y2+1)),update(c3,x2+1,y2+1,w*(y2+1));
        
            update(c4,x1,y1,w*x1*y1),update(c4,x2+1,y1,-w*(x2+1)*y1);
            update(c4,x1,y2+1,-w*x1*(y2+1)),update(c4,x2+1,y2+1,w*(x2+1)*(y2+1));
        }
        if(x==2)
        {
            int x1,y1,x2,y2;
            cin>>x1>>y1>>x2>>y2;
            cout<<get(x2,y2)-get(x2,y1-1)-get(x1-1,y2)+get(x1-1,y1-1)<<endl;
        }
    }
    return 0;
}

 

posted @ 2019-03-04 20:57  韵意  阅读(184)  评论(0编辑  收藏  举报