zoj3284Matrix Processing(二维树状数组)

题目请戳这里

题目大意:给一个矩阵,然后q个操作。有3种操作类型:

op = 0:按行优先原则从(x1,y1)到(x2,y2)所有元素都加一个k。

op = 1:按列优先原则从(x1,y1)到(x2,y2)所有元素都加上k。

op = 2:查询(x,y)处元素值。

题目分析:矩阵不大,但是查询很多。暴力会超时。于是高兴的写了一个二维线段树,结果华丽丽的TLE了。然后又不断调整姿势,还是TLE。。。

唉,二维线段树,感觉再也不会爱了。。。快哭了

这道题仔细看只有2种操作:区间修改和单点查询。所以这题可以直接用二维树状数组做。因为是修改区间查询点,所以要向下修改向上查询。

更新的时候,以行优先为例,得出来的更新区域不是一个完整的矩形。所以可以考虑将更新区域分解。有2种分法:做加法和做减法。2种方法都差不多,都是将更新区域分成3部分。我是用的减法,感觉方便些。

详情请见代码:

#include<cstdio>
#include<cstring>
#include<algorithm>

using namespace std;
const int N = 101;

int bit[N][N];
int n,m,c1,c2,r1,r2,op,k,s;
void init()
{
    for(int i = 1;i <= n;i ++)
        for(int j = 1;j <= m;j ++)
            bit[i][j] = 0;
}
void add(int x,int y,int val)
{
    if(x <= 0 || y <= 0)
        return;
    while(x)
    {
        int i = y;
        while(i)
        {
            bit[x][i] += val;
            i -= (i&-i);
        }
        x -= (x&-x);
    }
}
int sum(int x,int y)
{
    int ret = 0;
    while(x <= n)
    {
        int i = y;
        while(i <= m)
        {
            ret += bit[x][i];
            i += (i&-i);
        }
        x += (x&-x);
    }
    return ret;
}
void addretc(int x1,int y1,int x2,int y2,int val)
{
    if(x1 > x2 || y1 > y2)
        return ;
    add(x1 - 1,y1 - 1,val);
    add(x2,y2,val);
    add(x1 - 1,y2,-val);
    add(x2,y1 - 1,-val);
}

int main()
{
    int cas = 0;
    while(scanf("%d%d",&n,&m) != EOF)
    {
        init();
        int tmp;
//        if(cas)
//            puts("");
        for(int i = 1;i <= n;i ++)
            for(int j = 1;j <= m;j ++)
                scanf("%d",&tmp),addretc(i,j,i,j,tmp);
        scanf("%d",&s);
        printf("Case %d\n",++cas);
        while(s --)
        {
            scanf("%d",&op);
            if(op == 2)
            {
                scanf("%d%d",&r1,&c1);
                printf("%d\n",sum(r1,c1));
            }
            else
            {
                scanf("%d%d%d%d%d",&r1,&c1,&r2,&c2,&k);

                if(!op)
                {
                    if(r1 > r2)
                        swap(r1,r2),swap(c1,c2);
                    else if(r1 == r2 && c1 > c2)
                            swap(c1,c2);
                    addretc(r1,1,r2,m,k);
                    addretc(r1,1,r1,c1 - 1,-k);
                    addretc(r2,c2 + 1,r2,m,-k);
                }
                else
                {
                    if(c1 > c2)
                        swap(c1,c2),swap(r1,r2);
                    else if(c1 == c2 && r1 > r2)
                            swap(r1,r2);
                    addretc(1,c1,n,c2,k);
                    addretc(1,c1,r1 - 1,c1,-k);
                    addretc(r2 + 1,c2,n,c2,-k);
                }
            }
        }
    }
    return 0;
}


你可能感兴趣的:(数据结构)