题目就不贴了。0 - 1 矩阵,修改 + 询问。
看 ccl 写了一个二维线段树,好像时间被暴虐了 (1100 ms 吧)。。。于是无聊写了一下。。。
看到 0 - 1 矩阵,马上想到压位。。。然后对于每一位建树状数组。。。相当于分块树状数组了。。。
然后用树状数组做差分前缀和。。。每次都是 O(lgn) 的。。。
相当于我的回答是 O(lgn) 的,而修改是 O(n * lgn * 1000 / 64) 的。
结果竟然是 125 ms,rank 7(第三快的时间),而且空间小得出奇。。。压位真是神器啊。。。
错点:用 int 存 unsigned long long 做返回值了。。。结果各种 WA。。。不过好在养成了每次先拍的习惯。。。
Code :
#include <cstdio>
#include <cstdlib>
#include <cstring>
#define maxn 1000
#define maxs 62
#define ull unsigned long long
void getint(int & A)
{
char c = getchar();
for (; '0' > c || c > '9'; c = getchar());
A = c - '0', c = getchar();
for (; '0' <= c && c <= '9'; c = getchar()) A = A * 10 + c - '0';
}
int n, m, x1, y1, x2, y2;
ull block[maxs + 5];
ull a[maxn / maxs + 2][maxn + 1];
ull query(int A, int B)
{
ull * p = a[A], res = 0;
for (; B; B -= B & - B) res ^= p[B];
return res;
}
void modify(int A, int B1, int B2, const ull & C)
{
ull * p = a[A]; ++ B2;
for (; B1 <= n; B1 += B1 & - B1) p[B1] ^= C;
for (; B2 <= n; B2 += B2 & - B2) p[B2] ^= C;
}
void revise()
{
int i, j; ull k;
int L = (x1 - 1) / maxs + 1;
int R = (x2 - 1) / maxs + 1;
if (L == R)
{
k = block[x2 - x1 + 1] << ((x1 - 1) % maxs);
modify(L, y1, y2, k);
}
else
{
for (i = L + 1; i < R; ++ i) modify(i, y1, y2, block[maxs]);
j = L * maxs - x1 + 1, k = block[j] << (maxs - j);
modify(L, y1, y2, k);
j = R * maxs - x2, k = block[maxs - j];
modify(R, y1, y2, k);
}
}
void getans()
{
int A = (x1 - 1) / maxs + 1;
ull B = query(A, y1);
puts((B >> ((x1 - 1) % maxs)) & 1 ? "1" : "0");
}
void prepare()
{
int i; block[0] = 1;
for (i = 1; i <= maxs; ++ i) block[i] = block[i - 1] << 1;
for (i = 0; i <= maxs; ++ i) -- block[i];
}
int main()
{
freopen("2155.in", "r", stdin);
freopen("2155.out", "w", stdout);
int X; prepare();
for (getint(X); X --; )
{
getint(n), memset(a, 0, sizeof a);
for (getint(m); m --; )
if (getchar() == 'Q')
{
getint(x1), getint(y1);
getans();
}
else
{
getint(x1), getint(y1), getint(x2), getint(y2);
revise();
}
if (X) puts("");
}
return 0;
}