[BZOJ 3282] Tree 【LCT】

题目链接:BZOJ - 3282

 

题目分析

这道题是裸的LCT,包含 Link , Cut 和询问两点之间的路径信息。

写代码时出现的错误:Access(x) 的循环中应该切断的是原来的 Son[x][1] ,然而我写成了 Son[x][0]

 

代码

#include <iostream>
#include <cstdlib>
#include <cstdio>
#include <cstring>
#include <cmath>
#include <algorithm>

using namespace std;

inline void Read(int &Num)
{
	char c = getchar();
	bool Neg = false;
	while (c < '0' || c > '9')
	{
		if (c == '-') Neg = true;
		c = getchar();
	}
	Num = c - '0'; c = getchar();
	while (c >= '0' && c <= '9')
	{
		Num = Num * 10 + c - '0';
		c = getchar();
	}
	if (Neg) Num = -Num;
}
     
const int MaxN = 300000 + 5;

int n, m;
int A[MaxN], T[MaxN], Father[MaxN], Son[MaxN][2];

bool isRoot[MaxN], Rev[MaxN];

inline void Update(int x)
{
	T[x] = T[Son[x][0]] ^ T[Son[x][1]] ^ A[x];
}

inline void Reverse(int x)
{
	Rev[x] = !Rev[x];
	swap(Son[x][0], Son[x][1]);
}

inline void PushDown(int x)
{
	if (!Rev[x]) return;
	Rev[x] = false;
	if (Son[x][0]) Reverse(Son[x][0]);
	if (Son[x][1]) Reverse(Son[x][1]);
}

void Rotate(int x)
{
	int y = Father[x], f;
	PushDown(y); PushDown(x);
	if (x == Son[y][0]) f = 1;
	else f = 0;
	if (isRoot[y])
	{
		isRoot[y] = false;
		isRoot[x] = true;
	}
	else
	{
		if (y == Son[Father[y]][0]) Son[Father[y]][0] = x;
		else Son[Father[y]][1] = x;
	}
	Father[x] = Father[y];
	Son[y][f ^ 1] = Son[x][f];
	if (Son[x][f]) Father[Son[x][f]] = y;
	Son[x][f] = y;
	Father[y] = x;
	Update(y);
	Update(x);
}

void Splay(int x)
{
	int y;
	while (!isRoot[x])
	{
		y = Father[x];
		if (isRoot[y])
		{
			Rotate(x);
			break;
		}
		if (y == Son[Father[y]][0])
		{
			if (x == Son[y][0])
			{
				Rotate(y);
				Rotate(x);
			}
			else
			{
				Rotate(x);
				Rotate(x);
			}
		}
		else
		{
			if (x == Son[y][1])
			{
				Rotate(y);
				Rotate(x);
			}
			else
			{
				Rotate(x);
				Rotate(x);
			}
		}
	}
}

int Access(int x)
{
	int y = 0;
	while (x != 0)
	{
		Splay(x);
		PushDown(x);
		if (Son[x][1]) isRoot[Son[x][1]] = true;
		Son[x][1] = y;
		if (y) isRoot[y] = false;
		Update(x);
		y = x;
		x = Father[x];
	}
	return y;
}

void Make_Root(int x)
{
	int t = Access(x);
	Reverse(t);
}

int Find_Root(int x)
{
	int t = Access(x);
	while (Son[t][0] != 0) t = Son[t][0];
	return t;
}

int main()
{
	scanf("%d%d", &n, &m);
	for (int i = 1; i <= n; ++i)
	{
		Read(A[i]);
		T[i] = A[i];
		isRoot[i] = true;
		Father[i] = 0;
	}
	int f, x, y, t, fx, fy;
	for (int i = 1; i <= m; ++i)
	{
		Read(f); Read(x); Read(y);
		switch (f) 
		{
			case 0 : 
				Make_Root(x);
				t = Access(y);
				printf("%d\n", T[t]);
				break;
			
			case 1 :
				fx = Find_Root(x);
				fy = Find_Root(y);
				if (fx != fy)
				{
					Make_Root(x);
					Splay(x);
					Father[x] = y;
				}
				break;
				
			case 2 :
				Make_Root(x);
				Access(y);
				Splay(y);
				PushDown(y);
				if (Son[y][0] == x)
				{
					isRoot[Son[y][0]] = true;
					Father[Son[y][0]] = 0;
					Son[y][0] = 0;
					Update(y);
				}
				break;
				
			case 3 :
				Splay(x);
				A[x] = y;
				Update(x);
				break;
		}
	}
	return 0;
}

  

posted @ 2015-04-22 10:32  JoeFan  阅读(203)  评论(0编辑  收藏  举报