POJ 1195 Mobile Phone 最基础的二维线段树

题意:对一个矩阵不停的更新和查询,每次查询得到一个子矩阵的和。

最基础的二维线段树。感觉还不是很难,和最开始自己猜测的样子差不多——在一维的基础上,对每一个节点加上一棵子树,还是很形象的。

第一维还是表示X轴,然后每一个节点的子树表示在这一段区间内Y轴上的情况。

写完之后感觉自己以前的一维线段树有很多不足,冗杂的没有任何意义的计算不仅浪费了时间也浪费了大量的内存,是时候好好整理一下了。

PS:要是走之前就把这道题过了,也不至于现场赛时墨迹了那么久才出题。A掉之后去Status里面翻了一下,第一名竟然才跑了97ms,被甩了N条街唉。

#include <iostream>
#include <algorithm>
#include <cstdlib>
#include <cstdio>
#include <cstring>

using namespace std;

int st[2048][2048];

void updata_y(int s1,int s2,int T,int B,int x,int y,int a,int S)
{
    st[s1][s2] += a;
    if(T == B)
        return ;

    int mid = (T + B)>>1;

    if(y <= mid)
    {
        updata_y(s1,s2<<1,T,mid,x,y,a,S);
    }
    else
    {
        updata_y(s1,s2<<1|1,mid+1,B,x,y,a,S);
    }
}

void updata_x(int s1,int s2,int L,int R,int x,int y,int a,int S)
{
    updata_y(s1,s2,0,S-1,x,y,a,S);

    if(L == R)
        return ;

    int mid = (L + R)>>1;

    if(x <= mid)
    {
        updata_x(s1<<1,s2,L,mid,x,y,a,S);
    }
    else
    {
        updata_x(s1<<1|1,s2,mid+1,R,x,y,a,S);
    }
}

int query_y(int s1,int s2,int T,int B,int l,int r,int t,int b,int S)
{
    if(T == t && B == b)
    {
        return st[s1][s2];
    }

    int mid = (B + T)>>1;

    if(b <= mid)
    {
        return query_y(s1,s2<<1,T,mid,l,r,t,b,S);
    }
    if(mid < t)
    {
        return query_y(s1,s2<<1|1,mid+1,B,l,r,t,b,S);
    }
    return query_y(s1,s2<<1,T,mid,l,r,t,mid,S) + query_y(s1,s2<<1|1,mid+1,B,l,r,mid+1,b,S);
}

int query_x(int s1,int s2,int L,int R,int l,int r,int t,int b,int S)
{
    if(L == l && R == r)
    {
        return query_y(s1,s2,0,S-1,l,r,t,b,S);
    }

    int mid = (L + R)>>1;

    if(r <= mid)
    {
        return query_x(s1<<1,s2,L,mid,l,r,t,b,S);
    }
    if(mid < l)
    {
        return query_x(s1<<1|1,s2,mid+1,R,l,r,t,b,S);
    }

    return query_x(s1<<1,s2,L,mid,l,mid,t,b,S) + query_x(s1<<1|1,s2,mid+1,R,mid+1,r,t,b,S);
}

int main()
{
    int n,m;
    int x,y,a;
    int l,r,t,b;
    while(scanf("%d",&n) && n != 3)
    {
        if(n == 0)
        {
            scanf("%d",&m);
            memset(st,0,sizeof(st));
        }
        else if(n == 1)
        {
            scanf("%d %d %d",&x,&y,&a);
            updata_x(1,1,0,m-1,x,y,a,m);
        }
        else if(n == 2)
        {
            scanf("%d %d %d %d",&l,&t,&r,&b);
            printf("%d\n",query_x(1,1,0,m-1,l,r,t,b,m));
        }
    }
    return 0;
}

你可能感兴趣的:(POJ 1195 Mobile Phone 最基础的二维线段树)