注意:$LCT$ 在 $link$ 的时候必须要 makeroot.
假如要将 $y$ 连到 $x$ 上:
如果只是将 $y$ Access 并 splay 然后直接连到 $x$ 上的话你会发现 $y$ 在 $splay$ 中所有左儿子其实都在 $(x,y)$ 之间,而这显然就不对了.
code:
#include <cstdio>
#include <string>
#include <cstdlib>
#include <ctime>
#include <algorithm>
#define N 400006
using namespace std;
namespace IO {
void setIO(string s)
{
string in=s+".in";
string out=s+".out";
freopen(in.c_str(),"r",stdin);
freopen(out.c_str(),"w",stdout);
}
};
namespace LCT {
#define lson t[x].ch[0]
#define rson t[x].ch[1]
#define get(x) (t[t[x].f].ch[1]==x)
#define IsR(x) (!(t[t[x].f].ch[0]==x||t[t[x].f].ch[1]==x))
struct node {
int sum,son,ch[2],rev,f;
}t[N];
int sta[N];
inline void Pushup(int x)
{
t[x].sum=t[lson].sum^t[rson].sum^t[x].son;
}
inline void Mark(int x)
{
t[x].rev^=1;
swap(lson,rson);
}
inline void Pushdown(int x)
{
if(t[x].rev)
{
t[x].rev^=1;
if(lson) Mark(lson);
if(rson) Mark(rson);
}
}
inline void Rotate(int x)
{
int old=t[x].f,fold=t[old].f,which=get(x);
if(!IsR(old)) t[fold].ch[t[fold].ch[1]==old]=x;
t[old].ch[which]=t[x].ch[which^1],t[t[old].ch[which]].f=old;
t[x].ch[which^1]=old,t[old].f=x,t[x].f=fold;
Pushup(old),Pushup(x);
}
inline void Splay(int x)
{
int v=0,u=x,fa;
for(sta[++v]=u;!IsR(u);u=t[u].f) sta[++v]=t[u].f;
for(;v;--v) Pushdown(sta[v]);
for(u=t[u].f;(fa=t[x].f)!=u;Rotate(x))
if(t[fa].f!=u)
Rotate(get(fa)==get(x)?fa:x);
}
void Access(int x)
{
for(int y=0;x;y=x,x=t[x].f)
{
Splay(x);
t[x].son^=t[rson].sum;
t[x].son^=t[y].sum;
rson=y;
Pushup(x);
}
}
void Move_Root(int x)
{
Access(x);
Splay(x);
Mark(x);
}
int Find(int x)
{
Access(x);
while(lson) x=lson;
return x;
}
void Link_Edge(int x,int y)
{
Move_Root(x);
Move_Root(y);
t[y].f=x;
t[x].son^=t[y].sum;
Pushup(x);
}
void Cut_Edge(int x,int y)
{
Move_Root(x);
Access(y),Splay(y);
t[t[y].ch[0]].f=0;
t[y].ch[0]=0;
Pushup(y);
}
void Update(int x,int v)
{
Access(x);
Splay(x);
t[x].son^=v;
Pushup(x);
}
int query(int x,int y)
{
Move_Root(x);
Access(y);
return t[y].son;
}
#undef lson
#undef rson
};
struct SS {
int x,y,w;
SS(int x=0,int y=0,int w=0):x(x),y(y),w(w){}
}S[N];
int n;
int main()
{
srand(20011011);
// IO::setIO("input");
int i,j,m,tot=0,su=0;
scanf("%d%d%d",&i,&n,&m);
for(i=1;i<n;++i)
{
int x,y;
scanf("%d%d",&x,&y);
LCT::Link_Edge(x,y);
}
for(i=1;i<=m;++i)
{
int op;
scanf("%d",&op);
if(op==1)
{
int x,y,u,v;
scanf("%d%d%d%d",&x,&y,&u,&v);
LCT::Cut_Edge(x,y);
LCT::Link_Edge(u,v);
}
if(op==2)
{
int x,y,w;
scanf("%d%d",&x,&y);
w=rand();
S[++tot]=SS(x,y,w);
LCT::Update(x,w);
LCT::Update(y,w);
su^=w;
}
if(op==3)
{
int x;
scanf("%d",&x);
LCT::Update(S[x].x,S[x].w);
LCT::Update(S[x].y,S[x].w);
su^=S[x].w;
}
if(op==4)
{
int x,y;
scanf("%d%d",&x,&y);
printf("%s\n",LCT::query(x,y)==su?"YES":"NO");
}
}
return 0;
}