POJ 2155 二维线段树(压位水过)

来源:互联网 发布:java 运行lua 编辑:程序博客网 时间:2024/06/05 00:59

题目就不贴了。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 longvoid 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;}


原创粉丝点击