POJ 2155 二維線段樹(壓位水過)

題目就不貼了。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;
}


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章