UOJ207 共价大爷游长沙
Link
我们知道一条边被所有路径经过就是其一个端点的子树中包含了所有路径的一端。
那么我们可以给每条路径的端点rand一个随机权值,然后用LCT维护子树异或和,查询就是看子树异或和是否等于所有随机权值的异或和。
LCT维护子树信息+单点修改就是多维护一个虚子树信息,改变虚边的时候修改一下就好了。
这个方法的正确性还是挺高的,不过我不太会证。
#include<cstdio>
#include<cctype>
#include<cstdlib>
#include<iostream>
using std::rand;
using std::swap;
namespace IO
{
char ibuf[(1<<21)+1],*iS,*iT;
char Get(){return (iS==iT? (iT=(iS=ibuf)+fread(ibuf,1,(1<<21)+1,stdin),(iS==iT? EOF:*iS++)):*iS++);}
int read(){int x=0,c=Get();while(!isdigit(c))c=Get();while(isdigit(c))x=x*10+c-48,c=Get();return x;}
}using namespace IO;
const int N=100007;
int ch[N][2],fa[N],rev[N],sum[N],val[N];
struct node{int u,v,w;}t[N*3];
#define lc ch[x][0]
#define rc ch[x][1]
int nroot(int x){return ch[fa[x]][0]==x||ch[fa[x]][1]==x;}
void pushup(int x){sum[x]=sum[lc]^sum[rc]^val[x];}
void pushrev(int x){swap(lc,rc),rev[x]^=1;}
void pushdown(int x){if(rev[x])pushrev(lc),pushrev(rc),rev[x]=0;}
void pushall(int x){if(nroot(x))pushall(fa[x]);pushdown(x);}
void rotate(int x){int y=fa[x],z=fa[y],k=ch[y][1]==x;if(nroot(y))ch[z][ch[z][1]==y]=x;fa[x]=z,fa[y]=x,fa[ch[x][!k]]=y,ch[y][k]=ch[x][!k],ch[x][!k]=y,pushup(y);}
void splay(int x){pushall(x);for(int y;nroot(x);rotate(x)) if(nroot(y=fa[x])) rotate((ch[fa[y]][0]==y)^(ch[y][0]==x)? y:x);pushup(x);}
void access(int x){for(int y=0;x;x=fa[y=x])splay(x),val[x]^=sum[y]^sum[rc],rc=y,pushup(x);}
void makeroot(int x){access(x),splay(x),pushrev(x);}
void link(int x,int y){makeroot(x),makeroot(y),val[y]^=sum[x],fa[x]=y;}
void cut(int x,int y){makeroot(y),access(y),splay(x),fa[x]=0,val[y]^=sum[x];}
void update(int x,int w){access(x),splay(x),val[x]^=w;}
#undef lc
#undef rc
int main()
{
srand(19260817),read();int n=read(),m=read(),s=0,c=0;
for(int i=1;i<n;++i) link(read(),read());
for(int u,v,w;m;--m)
switch(read())
{
case 1:cut(read(),read()),link(read(),read());break;
case 2:u=read(),v=read(),w=rand()*32768+rand(),update(u,w),update(v,w),s^=w,t[++c]={u,v,w};break;
case 3:u=read(),update(t[u].u,t[u].w),update(t[u].v,t[u].w),s^=t[u].w;break;
case 4:u=read(),v=read(),makeroot(u),access(v),puts(val[v]==s?"YES":"NO");break;
}
}