poj1195二维线段树,区间求和,单点跟新

昨天搞了下二维线段树,今天来练练手~~感觉不错。

二维线段树~我这里用的是树中有树的方法,建的二维线段树。也就是x坐标一棵树。然后每个对应x坐标的区间,又有一颗树为y坐标。

理解了 也就跟一维线段树 差不多。

#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#define ll long long
#define maxn 1025
#define inf 0x3f3f3f3f
ll sum[maxn*4][maxn*4];
ll s;
 int n;
void pushup(int rt,int x)
{
    sum[x][rt]=sum[x][rt*2]+sum[x][rt*2+1];
}
void buildy(int rt,int left,int right,int xrt)//y坐标
{
    if(left==right) sum[xrt][rt]=0;
    else
    {
        int mid=(left+right)/2;
        buildy(rt*2,left,mid,xrt);
        buildy(rt*2+1,mid+1,right,xrt);
        pushup(rt,xrt);
    }
}
void build(int rt,int left,int right)//确定x坐标
{
    buildy(1,1,n,rt);

    if(left!=right)
    {
        int mid=(left+right)/2;
        build(rt*2,left,mid);
        build(rt*2+1,mid+1,right);
    }
}
void updatey(int rt,int left,int right,int y,int xrt,ll add)
{
    if(left==right&&left==y)
    {
        sum[xrt][rt]+=add;
        return ;
    }
    int mid=(left+right)/2;
    if(y<=mid) updatey(rt*2,left,mid,y,xrt,add);
    if(y>mid) updatey(rt*2+1,mid+1,right,y,xrt,add);
    pushup(rt,xrt);
}
void update(int rt,int left,int right,int x,int y,ll add)
{
    updatey(1,1,n,y,rt,add);
    if(left!=right)
    {
        int mid=(left+right)/2;
        if(x<=mid) update(rt*2,left,mid,x,y,add);
        if(x>mid) update(rt*2+1,mid+1,right,x,y,add);
    }
}
void queryY(int rt,int left,int right,int y1,int y2,int xrt)
{
    if(left>=y1&&right<=y2)
    {
        s+=sum[xrt][rt];
        return ;
    }
    int mid=(left+right)/2;
    if(y1<=mid) queryY(rt*2,left,mid,y1,y2,xrt);
    if(y2>mid) queryY(rt*2+1,mid+1,right,y1,y2,xrt);
}
void query(int rt,int left,int right,int x1,int y1,int x2,int y2)
{
    if(left>=x1&&right<=x2)
    {
        queryY(1,1,n,y1,y2,rt);
        return ;
    }
    int mid=(left+right)/2;
    if(x1<=mid) query(rt*2,left,mid,x1,y1,x2,y2);
    if(x2>mid) query(rt*2+1,mid+1,right,x1,y1,x2,y2);

}
int main()
{
    int op;
    int x,y;
    ll w;
    int x1,y1,x2,y2;
    while(scanf("%d",&op))
    {
        if(op==0){

            scanf("%d",&n);
            n++;
            build(1,1,n);
        }
        else if(op==1)
        {
            scanf("%d%d%lld",&x,&y,&w);
            x++,y++;
            update(1,1,n,x,y,w);
        }
        else if(op==2)
        {
            scanf("%d%d%d%d",&x1,&y1,&x2,&y2);
            s=0;
            x1++,y1++,x2++,y2++;
            query(1,1,n,x1,y1,x2,y2);
            printf("%lld\n",s);
        }
        else break;
    }
}



  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值