参考代码:blog.csdn.net/u012469987/article/details/47341457
写得有些懵逼了,谈下自己的见解。
所谓二维线段树就是线段树维护线段树,即树套树。
由于区间更新时只会挑某些树来更新,这些树不重不漏的覆盖了所有横坐标,但查找时却不一定找得到,直接说不好懂,举个例子吧。
比如一个4*4的矩阵,你先更新(1,2)(4,4),所以横坐标就是1和4,纵坐标就是2和4嘛,先更新横坐标,横坐标完全覆盖了根节点的范围,所以你就进去更新纵坐标,回来后直接return。也就是说你只更新了根节点的那棵树。
如果这时你要查询(2,2)(4,4),横坐标是2和4,纵坐标是2和4。先查询横坐标,由于横坐标没有完全覆盖根节点的范围,你就只能递归,于是你就错过了根节点上更新的信息了。
解决办法就是在查询横坐标时,每次递归前都进去查一下纵坐标。仔细想就会发现,虽然查了多次,但其实有且只有1次是有效的,因为信息只会唯一地存在在某棵子树内。
代码
#include<cstdio>
#include<string.h>
#define maxn 1010
#define m ((l+r)>>1)
#define ls (now<<1)
#define rs (ls|1)
using namespace std;
int N;
int tree[maxn<<2][maxn<<2];
char op[10];
int xl,yl,xr,yr,x,y;
int ans;
void UpDateY(int xnow,int l,int r,int now)
{
if(yl<=l&&r<=yr)
{
tree[xnow][now]^=1;
return;
}
if(yl<=m) UpDateY(xnow,l,m,ls);
if(yr>m) UpDateY(xnow,m+1,r,rs);
}
void UpDateX(int l,int r,int now)
{
if(xl<=l&&r<=xr)
{
UpDateY(now,1,N,1);
return;
}
if(xl<=m) UpDateX(l,m,ls);
if(xr>m) UpDateX(m+1,r,rs);
}
void QueryY(int xnow,int l,int r,int now)
{
ans^=tree[xnow][now];
if(l==r) return;
if(y<=m) QueryY(xnow,l,m,ls);
if(y>m) QueryY(xnow,m+1,r,rs);
}
void QueryX(int l,int r,int now)
{
QueryY(now,1,N,1);
if(l==r) return;
if(x<=m) QueryX(l,m,ls);
if(x>m) QueryX(m+1,r,rs);
}
int main()
{
int X;
scanf("%d",&X);
while(X--)
{
memset(tree,0,sizeof(tree));
int T;
scanf("%d %d",&N,&T);
while(T--)
{
scanf("%s",op);
if(op[0]=='C')
{
scanf("%d %d %d %d",&xl,&yl,&xr,&yr);
UpDateX(1,N,1);
}
else
{
scanf("%d %d",&x,&y);
ans=0;
QueryX(1,N,1);
printf("%d\n",ans);
}
}
if(X) puts("");
}
return 0;
}