poj2155 Matrix 二维线段树
二维线段树区间更新和单点查询,由于二维线段树不能传递标记,所以区间更新和一维不太一样,需要用到被更新的值以及更新操作的一些性质,还有要注意对query的影响。
这里操作是翻转,而且是单点查询,所以就直接在矩形块内更新,不把标记传递下去,查询的时候做一下微调,把所有经过的路径的标记都判断一遍,看是否需要翻转,这样就解决了这道题。
上一道是单点更新和区间求和,当然就不用标记了,把所有的第一维的第二层的y点全部更新,查询的时候不用查到最底层也能查到了。
二维线段树还是比较灵活,但这已经是最简单的树套树了。。。orz那些会各种线段树套平衡树,平衡树套主席树的。。。。
#include<iostream> #include<cstdio> #include<cstring> #include<cstdlib> #include<algorithm> #define lson l,m,rt<<1 #define rson m+1,r,rt<<1|1 using namespace std; typedef long long ll; const int maxn=1200; const int INF=1e9+10; int n,q; char op[5];int x,y,xt,yt; struct NodeY { int val; }; struct NodeX { NodeY ty[maxn<<2]; void build(int l,int r,int rt) { ty[rt].val=0; if(l==r) return; int m=(l+r)>>1; build(lson); build(rson); } void update(int L,int R,int l,int r,int rt) { if(L<=l&&r<=R){ ty[rt].val^=1; return; } int m=(l+r)>>1; if(L<=m) update(L,R,lson); if(R>m) update(L,R,rson); } int query(int p,int l,int r,int rt) { if(l==r) return ty[rt].val; int m=(l+r)>>1; if(p<=m) return ty[rt].val^query(p,lson); return ty[rt].val^query(p,rson); } };NodeX tx[maxn<<2]; void build(int l,int r,int rt) { tx[rt].build(1,n,1); if(l==r) return; int m=(l+r)>>1; build(lson); build(rson); } void update(int xL,int xR,int yL,int yR,int l,int r,int rt) { if(xL<=l&&r<=xR){ tx[rt].update(yL,yR,1,n,1); return; } int m=(l+r)>>1; if(xL<=m) update(xL,xR,yL,yR,lson); if(xR>m) update(xL,xR,yL,yR,rson); } int query(int x,int y,int l,int r,int rt) { int res=tx[rt].query(y,1,n,1); if(l==r) return res; int m=(l+r)>>1; if(x<=m) return res^query(x,y,lson); return res^query(x,y,rson); } int main() { int T;cin>>T; while(T--){ scanf("%d%d",&n,&q); build(1,n,1); while(q--){ scanf("%s",op); if(op[0]=='C'){ scanf("%d%d%d%d",&x,&y,&xt,&yt); update(x,xt,y,yt,1,n,1); } else{ scanf("%d%d",&x,&y); printf("%d\n",query(x,y,1,n,1)); } } if(T) puts(""); } return 0; }
没有AC不了的题,只有不努力的ACMER!