BZOJ 3132 上帝造题的七分钟(二维树状数组)

题目链接:http://61.187.179.132/JudgeOnline/problem.php?id=3132

题意:给出一个矩阵,两种操作:(1)将某个子矩阵的数字统一加上某个值;(2)查询某个子矩阵的数字之和。

思路:对于矩阵A,A[i][j]表示[i,j]-[n,m]的增量。那么子矩阵[1,1]-[x,y]的总和为:


struct BIT 
{
    int a[N][N];
    
    void add(int x,int y,int t)
    {
        int i,j;
        for(i=x;i<N;i+=i&-i)
        {
            for(j=y;j<N;j+=j&-j) a[i][j]+=t;
        }
    }
    
    int get(int x,int y)
    {
        int ans=0;
        int i,j;
        for(i=x;i;i-=i&-i)
        {
            for(j=y;j;j-=j&-j) ans+=a[i][j];
        }
        return ans;
    }
};

BIT a,b,c,d;


void add(int x1,int y1,int x2,int y2,int t)
{
    a.add(x1,y1,t); a.add(x2+1,y1,-t);
    a.add(x1,y2+1,-t); a.add(x2+1,y2+1,t);
    
    b.add(x1,y1,t*x1); b.add(x2+1,y1,-t*(x2+1));
    b.add(x1,y2+1,-t*x1); b.add(x2+1,y2+1,t*(x2+1));
    
    c.add(x1,y1,t*y1); c.add(x2+1,y1,-t*y1);
    c.add(x1,y2+1,-t*(y2+1)); c.add(x2+1,y2+1,t*(y2+1));
    
    d.add(x1,y1,t*x1*y1); d.add(x2+1,y1,-t*(x2+1)*y1);
    d.add(x1,y2+1,-t*x1*(y2+1)); d.add(x2+1,y2+1,t*(x2+1)*(y2+1));
}

int get(int x,int y)
{
    return (x+1)*(y+1)*a.get(x,y)-(y+1)*b.get(x,y)-(x+1)*c.get(x,y)+d.get(x,y);
}

int get(int x1,int y1,int x2,int y2)
{
    return get(x2,y2)-get(x2,y1-1)-get(x1-1,y2)+get(x1-1,y1-1);
}

int n,m;

int main()
{
    char op[10];
    int x1,y1,x2,y2,k;
    RD(op);
    RD(n,m);
    while(scanf("%s",op)!=-1)
    {
        if(op[0]=='L')
        {
            RD(x1,y1); RD(x2,y2,k);
            add(x1,y1,x2,y2,k);
        }
        else
        {
            RD(x1,y1); RD(x2,y2);
            PR(get(x1,y1,x2,y2));
        }
    }
}

  



  

原文地址:https://www.cnblogs.com/jianglangcaijin/p/3253686.html