LCT求调
查看原帖
LCT求调
526895
WYZ20030051楼主2023/9/4 15:17

rt,保龄力

#include<iostream>
#include<cstdio>
#include<cmath>
#include<string>
#include<cstring>
#include<algorithm>
#include<cassert>
#include<stack>
#include<queue>
#include<vector>
#include<map>
#include<cstdlib>
using namespace std;
#define ll long long
#define ull unsigned long long
int read()
{
	int now=0,nev=1; 
	char c=getchar();
	while(c<'0' || c>'9') 
	{ 
		if(c=='-') 
			nev=-1; 
		c=getchar();
	}
	while(c>='0' && c<='9') 
	{ 
		now=(now<<1)+(now<<3)+(c&15); 
		c=getchar(); 
	}
	return now*nev;
}
const int MAXN=1e6+10;
const int INF=1e9+7;
int n,m;
int v[MAXN];
int c[MAXN][2],fa[MAXN];//记录儿子节点和父亲节点(对于虚边,只记录儿子的父亲,而不记录父亲的儿子) 
int s[MAXN];
int st[MAXN];//手打栈
bool tag[MAXN];//懒标记 
bool isroot(int x)//判断当前节点是不是所在Splay中的根节点 
{
	if(c[fa[x]][0]==x || c[fa[x]][1]==x)
		return true;
	return false;
}
void pushup(int x)//上传信息,处理路径异或和 
{
	s[x]=s[c[x][0]]^s[c[x][1]]^v[x];
}
void overturn(int x)//翻转操作
{
	int lc=c[x][0];
	c[x][0]=c[x][1];
	c[x][1]=lc;
	tag[x]^=1;
}
void pushdown(int x)//释放懒标记并翻转对应的链 
{
	if(tag[x])
	{
		if(c[x][0])
			overturn(c[x][0]);
		if(c[x][1])
			overturn(c[x][1]);
		tag[x]=0;
	}
}
void rotate(int x)//旋转操作 
{
	int y=fa[x],z=fa[y];
	int k=c[y][1]==x;
	int w=c[x][!k];
	if(isroot(y))
	{
		if(c[z][1]==y)
			c[z][1]=x;
		else
			c[z][0]=x;
		c[x][!k]=y;
		c[y][k]=w;
	}
	if(w)
		fa[w]=y,fa[y]=x,fa[x]=z;
	pushup(y);
}
void Splay(int x)//只传了一个参数,因为所有操作的对象都是该Splay的根
{
	int y=x;
	int tt=0;
	st[++tt]=y;
	while(isroot(y))
		st[++tt]=y=fa[y];//不断入栈并处理每个是所在Splay的根节点的点 
	while(tt)//对栈内元素进行标记下传并清空栈 
		pushdown(st[tt--]);
	while(isroot(x))//对x的第二次操作 
	{
		y=fa[x];
		if(isroot(y))
			rotate((c[y][0]==x)^(c[fa[y]][0]==y)?x:y);
		rotate(x);
	}
	pushup(x);
}
void access(int x)//访问 
{
	for(int y=0;x;x=fa[y=x])
	{
		Splay(x);
		c[x][1]=x;
		pushup(x);
	}
}
void makeroot(int x)//换根
{
	access(x);
	Splay(x);
	overturn(x);
}
int findroot(int x)//在原树上找根
{
	access(x);
	Splay(x);
	while(c[x][0])
	{
		pushdown(x);
		x=c[x][0];
	}
	Splay(x);
	return x;
}
void split(int x,int y)//提取x到y的路径 
{
	makeroot(x);
	access(y);
	Splay(y);
}
void link(int x,int y)//连接x到y的边
{
	makeroot(x);
	if(findroot(y)!=x)
		fa[x]=y;
} 
void cut(int x,int y)//断掉x到y的边 
{
	makeroot(x);
	if(findroot(y)==x && fa[y]==x && !c[y][0])
	{
		fa[y]=c[x][1]=0;
		pushup(x);
	}
}
int main()
{
	n=read(),m=read();
	for(int i=1;i<=n;i++)
		v[i]=read();
	for(int i=1;i<=m;i++)
	{
		int op;
		op=read();
		int x,y;
		x=read(),y=read();
		if(op==0)
		{
			split(x,y);
			printf("%d\n",s[y]);
		}
		if(op==1)
			link(x,y);
		if(op==2)
			cut(x,y);
		if(op==3)//先把x转到根节点再修改x节点的权值,不影响结果 
		{
			Splay(x);
			v[x]=y;
		}
	}
	return 0;
}
2023/9/4 15:17
加载中...