Problem
Solution
这道题可以维护子树hash值来做。这个hash函数要求仅与各个数的值有关。
如果边(x,y)在所有的路径上,那么我们可以认为在子树x/y中,hash值是要等于某个值的(这个值我们可以维护总的hash值)。而一个比较好的hash就是异或和,为了不冲突我们可以用2的幂来赋值,但注意到路径可能比较多,所以直接rand一个大数,冲突的概率也是比较小的。
而这道题要求要维护子树信息,用s1代表虚儿子的异或和,s2代表总的异或和,然后大概就是板子了。
Code
#include <algorithm>
#include <cstdlib>
#include <cstdio>
#define pd(x) if(rev[x])pushdown(x)
#define pushup(x) s2[x]=s2[ch[x][0]]^s2[ch[x][1]]^s1[x]
#define rg register
using namespace std;
const int maxn=100010;
struct data{int x,y,v;}opr[maxn*3];
int n,m,opt,top,cnt,f[maxn],ch[maxn][2],rev[maxn],s2[maxn],s1[maxn],stk[maxn];
template <typename Tp> inline void read(Tp &x)
{
x=0;char ch=getchar();
while(ch<'0'||ch>'9') ch=getchar();
while(ch>='0'&&ch<='9') x=x*10+ch-'0',ch=getchar();
}
inline int isroot(int x){return ch[f[x]][0]!=x&&ch[f[x]][1]!=x;}
void pushdown(int x)
{
rev[ch[x][0]]^=1;rev[ch[x][1]]^=1;
swap(ch[x][0],ch[x][1]);rev[x]=0;
}
void rotate(int x)
{
int fa=f[x],ff=f[fa],l,r;
if(ch[fa][0]==x) l=0;else l=1;r=l^1;
if(!isroot(fa)){if(ch[ff][0]==fa) ch[ff][0]=x;else ch[ff][1]=x;}
f[x]=ff;f[fa]=x;f[ch[x][r]]=fa;
ch[fa][l]=ch[x][r];ch[x][r]=fa;
pushup(fa);pushup(x);
}
void splay(int x)
{
stk[top=1]=x;
for(int i=x;!isroot(i);i=f[i]) stk[++top]=f[i];
for(;top;top--) pd(stk[top]);
while(!isroot(x))
{
int fa=f[x],ff=f[fa];
if(!isroot(fa))
{
if((ch[fa][0]==x)^(ch[ff][0]==fa)) rotate(x);
else rotate(fa);
}
rotate(x);
}
}
void access(int x){for(int t=0;x;t=x,x=f[x]) splay(x),s1[x]^=s2[ch[x][1]]^s2[t],ch[x][1]=t,pushup(x);}
void makeroot(int x){access(x);splay(x);rev[x]^=1;}
int find(int x){access(x);splay(x);while(ch[x][0]) x=ch[x][0];return x;}
void split(int x,int y){makeroot(x);access(y);splay(y);}
void cut(int x,int y){split(x,y);if(ch[y][0]==x) ch[y][0]=f[x]=0;pushup(y);}
void link(int x,int y){makeroot(x);makeroot(y);f[x]=y;s1[y]^=s2[x];pushup(y);}
void update(int x,int v){access(x);splay(x);s2[x]^=v;s1[x]^=v;}
//link中都makeroot以及update中的access+splay是因为懒得向上更新
int main()
{
#ifndef ONLINE_JUDGE
freopen("in.txt","r",stdin);
#endif
srand(19260817);
int x,y,v,s=0;
read(x);read(n);read(m);
for(rg int i=1;i<n;i++)
{
read(x);read(y);
link(x,y);
}
while(m--)
{
read(opt);
if(opt==1){read(x);read(y);cut(x,y);read(x);read(y);link(x,y);}
else if(opt==2)
{
read(x);read(y);v=rand();
opr[++cnt]=(data){x,y,v};
s^=v;update(x,v);update(y,v);
}
else if(opt==3)
{
read(x);s^=opr[x].v;
update(opr[x].x,opr[x].v);update(opr[x].y,opr[x].v);
}
else
{
read(x);read(y);split(x,y);
if(s1[y]==s) puts("YES");
else puts("NO");
}
}
return 0;
}