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

题目大意:

对一个矩阵上的某个值进行改动。然后求出子矩阵的和。


思路分析:

这题discuss 上说二维线段树过不了。

所以二维树状数组搞。

理解树状数组的意义就是 1 - n 上全部的和。

然后两重循环。


#include <iostream>
#include <cstring>
#include <cstdio>
#include <algorithm>
#define maxn 1040
#define lowbit(x) (x&(-x))

using namespace std;
int C[maxn][maxn];
int n;
void add(int x,int y,int a)
{
    for(int i=x;i<=n;i+=lowbit(i))
    {
        for(int j=y;j<=n;j+=lowbit(j))
        {
            C[i][j]+=a;
        }
    }
    //printf("out %d %d
",x,y);
}

int Sum(int L,int B,int R,int T)
{
    int res=0;
    for(; R>0 ; R -=lowbit(R))
    {
        int p=0,q=0;
        for(int i=T ; i>0 ; i-=lowbit(i))p+=C[R][i];
        for(int i=B-1; i>0 ; i-=lowbit(i))q+=C[R][i];
        res+=p-q;
    }
    int ret=0;
    for(L=L-1; L>0 ;L-=lowbit(L))
    {
        int p=0,q=0;
        for(int i=T; i>0 ;i-=lowbit(i))p+=C[L][i];
        for(int i=B-1; i>0 ;i-=lowbit(i))q+=C[L][i];
        ret+=p-q;
    }
    //printf("%d %d
",res,ret);
    return res-ret;
}

void debug()
{
    for(int i=1;i<=4;i++)
    {
        for(int j=1;j<=4;j++)
        {
            printf("%d ",C[i][j]);
        }
        puts("");
    }
}

int main()
{
    int op;
    while(scanf("%d",&op)!=EOF)
    {
        if(op==0)
        {
            scanf("%d",&n);
            memset(C,0,sizeof C);
        }
        else if(op==1)
        {
            int x,y;
            int a;
            scanf("%d%d%d",&x,&y,&a);
            x++,y++;
            add(x,y,a);
        }
        else if(op==2)
        {
            int L,B,R,T;
            scanf("%d%d%d%d",&L,&B,&R,&T);
            L++,B++,R++,T++;
            printf("%d
",Sum(L,B,R,T));
        }
        else break;
        //debug();
    }
    return 0;
}


原文地址:https://www.cnblogs.com/blfbuaa/p/6873593.html