[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;
}

  

时间: 2024-11-13 20:17:21

[BZOJ 3282] Tree 【LCT】的相关文章

BZOJ 3282 Tree(LCT)

[题目链接] http://www.lydsy.com/JudgeOnline/problem.php?id=3282 [题目大意] 0:后接两个整数(x,y),代表询问从x到y的路径上的点的权值的xor和.保证x到y是联通的. 1:后接两个整数(x,y),代表连接x到y,若x到Y已经联通则无需连接. 2:后接两个整数(x,y),代表删除边(x,y),不保证边(x,y)存在. 3:后接两个整数(x,y),代表将点X上的权值变成Y. [题解] LCT练习题 [代码] #include <cstdi

BZOJ 3282 Tree Link-Cut-Tree(LCT)

题目大意: 给定N个点以及每个点的权值,要你处理接下来的M个操作.操作有4种.操作从0到3编号.点从1到N编号. 0:后接两个整数(x,y),代表询问从x到y的路径上的点的权值的xor和.保证x到y是联通的. 1:后接两个整数(x,y),代表连接x到y,若x到Y已经联通则无需连接. 2:后接两个整数(x,y),代表删除边(x,y),不保证边(x,y)存在. 3:后接两个整数(x,y),代表将点X上的权值变成Y. 只有会员才知道的世界...有个会员的大神真好 LCT的入门题,切完2631之后这个就

bzoj 3159: 决战【LCT】

只是想复健一下LCT没想到做了不得了的题--调了两天QAQ 题解是这么说的: 但是果然还不太理解--因为swap的前后问题调了好久,(所以一开始养成的习惯后面就不要再改啦-- 总之大概就是把对位置lct的操作映射到权值lct上,然后权值lct可以随便转没问题,只要位置lct不动就可以-- 注意reverse!! #include<iostream> #include<cstdio> #include<cstring> using namespace std; const

BZOJ 1468 Tree 【模板】树上点分治

1 #include<cstdio> 2 #include<algorithm> 3 #define N 50010 4 #define M 500010 5 #define rg register 6 #define LL long long 7 using namespace std; 8 int n,m,cnt,root,tot,totnow,totbf; 9 int last[N],size[N],mxsize[N],dep[N],tmp[N],mg[N]; 10 LL a

HDU2489 Minimal Ratio Tree 【DFS】+【最小生成树Prim】

Minimal Ratio Tree Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total Submission(s): 2382    Accepted Submission(s): 709 Problem Description For a tree, which nodes and edges are all weighted, the ratio of it is

POJ--3013--Big Christmas Tree【dijkstra_heap】

题意:要造一个圣诞树(可以想象成倒过来的树结构),有n个节点,m条边,并告诉你边的信息,两条边之间有个单位造价, 一条树枝的造价=它上面的节点的重量以及节点子树的重量 * 这条树枝的单位造价. 需求出造这个圣诞树的最小造价,也有可能造不出. 画画图可以看出,总造价 = 每一点的重量 * 它到节点的最短路径,所以这道题其实就是个最短路 题目比较坑,dist数组会越界,需用long long,并且INF不能以int的最大值来赋值.边也不是他给的5W条,我开到20W才AC 我用了dijkstra+he

606. Construct String from Binary Tree 【easy】

606. Construct String from Binary Tree [easy] You need to construct a string consists of parenthesis and integers from a binary tree with the preorder traversing way. The null node needs to be represented by empty parenthesis pair "()". And you

HDOJ--4786--Fibonacci Tree【生成树】

题意:给出n个点,m条边,和边的信息.边有两种颜色,白色和黑色,现要求构造一个生成树,看能否满足白边的数量是斐波那契数. 这道题比赛的时候,小白想到了一种方法:按边颜色排序后,先用白边优先建树,求出最大白边最大个数maxm,再用黑边优先建树,求出白边最小个数minm,看这两个范围内是否存在斐波那契数. 听上去感觉还挺有道理,但是不知道怎么证明正确性,后来想想,生成树构造完之后,再添加任意一条边都会产生回路,而产生回路之后就有边会被替换,而minm是最少的白边数,也就是minm个白边是不会被换掉的

BZOJ 3282: Tree [LCT]

3282: Tree Time Limit: 30 Sec  Memory Limit: 512 MBSubmit: 1677  Solved: 744[Submit][Status][Discuss] Description 给定N个点以及每个点的权值,要你处理接下来的M个操作.操作有4种.操作从0到3编号.点从1到N编号. 0:后接两个整数(x,y),代表询问从x到y的路径上的点的权值的xor和.保证x到y是联通的. 1:后接两个整数(x,y),代表连接x到y,若x到Y已经联通则无需连接.