昨天搞了下二维线段树,今天来练练手~~感觉不错。
二维线段树~我这里用的是树中有树的方法,建的二维线段树。也就是x坐标一棵树。然后每个对应x坐标的区间,又有一颗树为y坐标。
理解了 也就跟一维线段树 差不多。
#include
#include
#include
#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;
}
}