楼教主的二维线段树(树状数组) ---------------这一题是真的不知道怎么做 ,但还是AC了...
题目我就不贴了...我就简单说一下题意:
1000*1000的矩阵,给你50000个操作
C操作 对从左上角(x1,y1)到右下角(x2,y2)的矩形中所有元素取反
Q操作 查询某坐标下元素的值
一看就是经典树状数组或者线段树了,大部分题解都很偷懒都是用二维树状数组的快速写法...
我在这里就用二维线段树来解了,不过线段树明显开销比树状数组大很多,线段树在结构体上要开4倍
这道题是二维因此比树状数组整整大了16倍,内存爆的很明显...
用int绝对MLE无误...于是我用了short竟然过了太意外...只能说数据比较水卡内存还没卡到变态程度...
线段树用的是自己写的模板...稍微修改一下处理二维处理区间和,区间极值都没问题
很经典的树套树...X轴(row)为母树,Y轴(column)为子树 ----------------其实随便怎么构建都行
对母线段树的每一个区间再构建一棵子线段树...每次更新的时候直接更新子树的值,查询同理...
母树不需要储存任何数据...只要构建起来为子树查询就行了
所以应该能用二维数组进行一个优化...这里我智商捉急暂时没想到快速的构建办法....(树状数组的那个方法简直太神了)
每个函数都要写两个真是坑爹死了...以至于太长写了4K...
/*Template*/
/*POJ 2155 */
/*52728 KB 1782 ms */
#include <algorithm>
#include <bitset>
#include <complex>
#include <deque>
#include <functional>
#include <iomanip>
#include <iostream>
#include <limits>
#include <list>
#include <map>
#include <numeric>
#include <queue>
#include <set>
#include <sstream>
#include <stack>
#include <string>
#include <utility>
#include <vector>
#include <cassert>
#include <cctype>
#include <climits>
#include <cmath>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <ctime>
using namespace std;
//typedef long long LL;
//typedef __int64 LL;
//Number
#define EPS 1e-8
#define MAXN 1050
#define INF (1<<30)
#define MOD 99991
//Math
#define max(a,b) ((a)>(b)?(a):(b))
#define min(a,b) ((a)<(b)?(a):(b))
int gcd(int a,int b){return b?gcd(b,a%b):a;}
int lcm(int a,int b){return a*b/gcd(a,b);}
//Segment Tree
#define L(t) (t << 1) //Left son
#define R(t) (t << 1 | 1) //Right son
#define mid(a,b) ((a+b)>>1) //Get Mid
//BIT
#define lowbit(a) (a&-a) //Get Lowbit
struct sub_node
{
short l,r,val;
}sub_tree[MAXN*4][MAXN*4];
struct node //main tree
{
short l,r;
}tree[MAXN*4];
void sub_build(int mroot,int l,int r,int root)
{
sub_tree[mroot][root].l=l;
sub_tree[mroot][root].r=r;
sub_tree[mroot][root].val=0;
if(l==r) return ;
int m=mid(l,r);
sub_build(mroot,l,m,L(root));
sub_build(mroot,m+1,r,R(root));
}
void build(int l,int r,int root)
{
tree[root].l=l;
tree[root].r=r;
sub_build(root,0,MAXN,1);
if(l==r) return ;
int m=mid(l,r);
build(l,m,L(root));
build(m+1,r,R(root));
}
void sub_modify(int mroot,int l,int r,int root,int val)
{
if(sub_tree[mroot][root].l==l && sub_tree[mroot][root].r==r)
{
sub_tree[mroot][root].val+=val;
return ;
}
int m = mid(sub_tree[mroot][root].l,sub_tree[mroot][root].r);
if(r <= m)
sub_modify(mroot,l,r,L(root),val);
else if(l > m)
sub_modify(mroot,l,r,R(root),val);
else
{
sub_modify(mroot,l,m,L(root),val);
sub_modify(mroot,m+1,r,R(root),val);
}
}
void modify(int l,int r,int ly,int ry,int root,int val)
{
if(tree[root].l==l && tree[root].r==r)
{
sub_modify(root,ly,ry,1,val);
return ;
}
int m = mid(tree[root].l,tree[root].r);
if(r <= m)
modify(l,r,ly,ry,L(root),val);
else if(l > m)
modify(l,r,ly,ry,R(root),val);
else
{
modify(l,m,ly,ry,L(root),val);
modify(m+1,r,ly,ry,R(root),val);
}
}
int sub_query(int mroot,int x,int root)
{
if(sub_tree[mroot][root].l==sub_tree[mroot][root].r)
return sub_tree[mroot][root].val;
int m = mid(sub_tree[mroot][root].l,sub_tree[mroot][root].r);
if(x <= m)
return sub_tree[mroot][root].val+sub_query(mroot,x,L(root));
else
return sub_tree[mroot][root].val+sub_query(mroot,x,R(root));
}
int query(int x,int y,int root)
{
if(tree[root].l==tree[root].r)
return sub_query(root,y,1);
int m = mid(tree[root].l,tree[root].r);
if(x <= m)
return sub_query(root,y,1) + query(x,y,L(root));
else
return sub_query(root,y,1) + query(x,y,R(root));
}
int main()
{
// freopen("in.txt","r",stdin);
// freopen("out.txt,"w",stdout);
int n ;
scanf("%d",&n);
while(n--)
{
build(0,MAXN,1);
int i,n,t;
scanf("%d%d",&n,&t);
for(i=0;i<t;i++)
{
getchar();
char x;
int a,b,c,d;
scanf("%c",&x);
if(x=='C')
{
scanf("%d%d%d%d",&a,&b,&c,&d);
modify(a,c,b,d,1,1);
}
else
{
scanf("%d%d",&a,&b);
cout<<query(a,b,1)%2<<endl;
}
}
puts("");
}
return 0;
}