题目:http://poj.org/problem?id=2155
题意:给一个N*N的全是0的矩阵,每次操作都是选一个子矩阵对其中每一项都取反。每次询问一个具体位置的值
分析:这题很明显的是个二维线段树模板题,但是在具体实现过程中由于一种是用延迟更新的做法导致了几次TLE。。以前从没遇到过用了延迟更新还会超时的情况,于是认真分析了一下,发现由于每次查询都一定查到叶子节点,所以延时更新完全没有作用,但是又不能每次更新都更新到叶子节点。再参考过discuss里面的代码之后,发现让所有节点之间都没有关系即不再使用线段树的区间和功能之后可以实现想利用了延迟更新一样的时间,这种方法是建立在操作是取反这种有循环节的操作上。
代码:
#include<cstdio>
#include<iostream>
#include<cstring>
#include<algorithm>
#include<vector>
#include<cmath>
#define N 1005
using namespace std;
int tree[N<<2][N<<2];
int n,m,ans;
void inity(int cur,int l,int r,int id)
{
tree[cur][id]=0;
if(l==r)return ;
int mid=(l+r)>>1;
inity(cur,l,mid,id<<1);
inity(cur,mid+1,r,id<<1|1);
}
void initx(int l,int r,int id)
{
inity(id,1,n,1);
if(l==r)return ;
int mid=(l+r)>>1;
initx(l,mid,id<<1);
initx(mid+1,r,id<<1|1);
}
void queryy(int cur,int pos,int l,int r,int id)
{
ans^=tree[cur][id];
if(l==r)return;
int mid=(l+r)>>1;
if(pos<=mid)queryy(cur,pos,l,mid,id<<1);
else queryy(cur,pos,mid+1,r,id<<1|1);
}
void queryx(int cur,int pos,int l,int r,int id)
{
queryy(id,pos,1,n,1);
if(l==r)return ;
int mid=(l+r)>>1;
if(cur<=mid)queryx(cur,pos,l,mid,id<<1);
else queryx(cur,pos,mid+1,r,id<<1|1);
}
void updatay(int cur,int ql,int qr,int l,int r,int id)
{
if(ql<=l&&r<=qr)
{
tree[cur][id]^=1;
return ;
}
int mid=(l+r)>>1;
if(ql<=mid)updatay(cur,ql,qr,l,mid,id<<1);
if(qr>mid)updatay(cur,ql,qr,mid+1,r,id<<1|1);
}
void updatax(int qlx,int qrx,int qly,int qry,int l,int r,int id)
{
if(qlx<=l&&r<=qrx)
{
updatay(id,qly,qry,1,n,1);
return ;
}
int mid=(l+r)>>1;
if(qlx<=mid)updatax(qlx,qrx,qly,qry,l,mid,id<<1);
if(qrx>mid)updatax(qlx,qrx,qly,qry,mid+1,r,id<<1|1);
}
int main()
{
int t;scanf("%d",&t);
while(t--)
{
scanf("%d%d",&n,&m);
initx(1,n,1);
while(m--)
{
char c;cin>>c;
if(c=='Q')
{
int x,y;scanf("%d%d",&x,&y);
ans=0;
queryx(x,y,1,n,1);
printf("%d\n",ans);
}
else
{
int x1,x2,y1,y2;scanf("%d%d%d%d",&x1,&y1,&x2,&y2);
updatax(x1,x2,y1,y2,1,n,1);
}
}
if(t)printf("\n");
}
return 0;
}