Description
有一棵树,会改变它的形态。
有一个路径集合,初始为空,路径集合会被更改。
询问操作是询问一条边是否被路径集合所有路径经过。
n<=100000
Analysis
对于一条边(x,y),如果所有路径都经过它,当且仅当所有路径中的仅一个端点在以x为根,y的子树内
我们对每一个路径随机一个权值,然后每次加入删除路径时,将两个段点的点权异或上这个权值,然后用动态树维护子树权值异或和,每次询问对应子树内的权值异或和是否是当前所有路径的权值异或和
Orz myy
Code
#include<cstdio>
#include<cstring>
#include<algorithm>
#define fo(i,a,b) for(int i=a;i<=b;++i)
#define fd(i,b,a) for(int i=b;i>=a;--i)
#define max(x,y) ((x)>(y)?(x):(y))
#define min(x,y) ((x)<(y)?(x):(y))
#define mset(a,x) memset(a,x,sizeof(a))
using namespace std;
typedef long long ll;
char ch;
void read(int &n){n=0;int p=1;for(ch=getchar();ch<'0' || ch>'9';ch=getchar())if(ch=='-') p=-1;for(;'0'<=ch && ch<='9';ch=getchar()) n=n*10+ch-'0';n*=p;}
const int N=1e5+5,M=3e5+5;
int n,m,stk[N],f[N],p[N],a[N][2],key[N],sum[N],vir[N];
bool rev[N];
int pd(int x){return x==a[f[x]][1];}
void update(int x)
{
sum[x]=key[x]^sum[a[x][0]]^sum[a[x][1]]^vir[x];
}
void turn(int x)
{
swap(a[x][0],a[x][1]);
rev[x]^=1;
}
void down(int x)
{
if(!rev[x]) return;
turn(a[x][0]);turn(a[x][1]);
rev[x]=0;
}
void remove(int x,int y)
{
for(;x!=y;x=f[x]) stk[++stk[0]]=x;
while(stk[0]) down(stk[stk[0]--]);
}
void rotate(int x)
{
int y=f[x],z=pd(x);
f[x]=f[y];
if(f[y]) a[f[y]][pd(y)]=x;
else p[x]=p[y],p[y]=0;
a[y][z]=a[x][1-z];
if(a[x][1-z]) f[a[x][1-z]]=y;
f[y]=x,a[x][1-z]=y;
update(y);
}
void splay(int x,int y)
{
remove(x,y);
for(;f[x]!=y;rotate(x))
if(f[f[x]]!=y) rotate(pd(x)==pd(f[x])?f[x]:x);
update(x);
}
void access(int x)
{
for(int y=0;x;y=x,x=p[x])
{
splay(x,0);
f[a[x][1]]=0,p[a[x][1]]=x;
vir[x]^=sum[a[x][1]];
a[x][1]=y,f[y]=x,p[y]=0;
vir[x]^=sum[y];
update(x);
}
}
void makeroot(int x)
{
access(x);
splay(x,0);
turn(x);
}
void link(int x,int y)
{
makeroot(x);makeroot(y);
p[x]=y;
vir[y]^=sum[x];
}
void cut(int x,int y)
{
makeroot(x);
access(y);
splay(y,0);
f[x]=0,a[y][0]=0;
update(y);
}
int query(int x)
{
access(x);
return key[x]^vir[x];
}
struct Path
{
int x,y,z;
Path(int _x=0,int _y=0,int _z=0):x(_x),y(_y),z(_z){}
}path[M];
int main()
{
srand(19260817);rand();
int ID,T,tp,x,y,z,u,v,val=0;
read(ID),read(n),read(T);
fo(i,1,n-1) read(x),read(y),link(x,y);
while(T--)
{
read(tp),read(x);
if(tp==1)
{
read(y),read(u),read(v);
cut(x,y);
link(u,v);
}
else
if(tp==2)
{
read(y);
path[++m]=Path(x,y,(unsigned int)(rand()*rand()+rand())%int(2e9));
val^=path[m].z;
makeroot(x);key[x]^=path[m].z;update(x);
makeroot(y);key[y]^=path[m].z;update(y);
}
else
if(tp==3)
{
int id=x;
x=path[id].x,y=path[id].y,z=path[id].z;
val^=z;
makeroot(x);key[x]^=z;update(x);
makeroot(y);key[y]^=z;update(y);
}
else
{
read(y);makeroot(y);
makeroot(x);
int t=query(y);
puts(t==val?"YES":"NO");
}
}
return 0;
}