特地说明是zkw线段树,而不是常规线段树,这道题好像故意卡二维线段树,晕啊。
都已经故意卡线段树了,zkw版线段树还是能过(700ms+),这说明zkw版线段树还是非常值得学习的!
这道题各种算法的效率比较:
常规二维线段树:TLE
二维zkw线段树:700ms+
二维树状数组:450ms+
二维zkw线段树的写法:
#include<iostream>
using namespace std;
bool tree[5010][5010];
int M;
void update_y(int x, int y1, int y2)
{
y1 = y1 - 1 + M;
y2 = y2 + 1 + M;
while(y1^y2^1)
{
if(~y1&1)
tree[x][y1^1] = !tree[x][y1^1];
if(y2&1)
tree[x][y2^1] = !tree[x][y2^1];
y1 >>= 1;
y2 >>= 1;
}
}
void update(int x1, int y1, int x2, int y2)
{
x1 = x1 - 1 + M;
x2 = x2 + 1 + M;
while(x1^x2^1)
{
if(~x1&1)
update_y(x1^1, y1, y2);
if(x2&1)
update_y(x2^1, y1, y2);
x1 >>= 1;
x2 >>= 1;
}
}
bool find_y(int x, int y)
{
y += M;
bool re = false;
while(y)
{
if(tree[x][y])
re = !re;
y >>= 1;
}
return re;
}
bool find_x(int x, int y)
{
x += M;
bool re = false;
while(x)
{
re = re ^ find_y(x, y);
x >>= 1;
}
return re;
}
int main()
{
int tot;
int n, m;
char str[5];
int a, b, c, d;
scanf("%d", &tot);
for(int i = 0; i < tot; i++)
{
if(i)putchar(10);
memset(tree, 0, sizeof(tree));
scanf("%d%d", &n, &m);
M = 1;
while(M-2 < n) M <<= 1;
for(int j = 1; j <= m; j++)
{
scanf("%s", str);
if(str[0] == 'C')
{
scanf("%d%d%d%d", &a, &b, &c, &d);
update(a, b, c, d);
}
else if(str[0] == 'Q')
{
scanf("%d%d", &a, &b);
if(find_x(a, b))
printf("1\n");
else
printf("0\n");
}
}
}
}