# 动态树~LCT总结

1、如果x和y不在同一棵树上则在xy连边

2、如果x和y在同一棵树上并且x!=y则把x换为树根并把y和y的父亲分离

3、如果x和y在同一棵树上则x到y的路径上所有的点权值+w

4、如果x和y在同一棵树上则输出x到y路径上的最大值

#include <cstdio>
#include <iostream>
using namespace std;
#define N 300010
#define INF (1<<30)
struct node
{
node *p,*ch[2];
}nodes[N],*cur,*null;
int n,m,u,v,w;
node *newnode(int key)
{
cur->p=cur->ch[0]=cur->ch[1]=null;
cur->mx=cur->val=key;
cur->rev=0;
return cur++;
}
void init()
{
null=nodes;
null->p=null->ch[0]=null->ch[1]=null;
null->mx=null->val=-INF;
null->rev=0;
cur=nodes+1;
}
struct dynamictree
{
bool isroot(node *x)//判根
{
return x==null || x->p->ch[0]!=x && x->p->ch[1]!=x;
}
void pushup(node *x)
{
x->mx=max(x->val,max(x->ch[0]->mx,x->ch[1]->mx));
}
void pushdown(node *x)
{
if(x==null) return;
if(x->rev)
{
x->rev=0;
if(x->ch[0]!=null) x->ch[0]->rev^=1;
if(x->ch[1]!=null) x->ch[1]->rev^=1;
swap(x->ch[0],x->ch[1]);
}
{
}
}
void rotate(node *x,int f)
{
if(isroot(x)) return;
node *y=x->p;
y->ch[!f]=x->ch[f];
x->p=y->p;
if(x->ch[f]!=null) x->ch[f]->p=y;
if(y!=null)
{
if(y==y->p->ch[1]) y->p->ch[1]=x;
else if(y==y->p->ch[0]) y->p->ch[0]=x;
}
x->ch[f]=y;
y->p=x;
pushup(y);
}
void splay(node *x)
{
static node *sta[N];
int top=1;
sta[0]=x;
for(node *y=x;!isroot(y);y=y->p)
sta[top++]=y->p;
while (top) pushdown(sta[--top]);
while (!isroot(x))
{
node *y=x->p;
if(isroot(y)) rotate(x,x==y->ch[0]);
else
{
int f=y->p->ch[0]==y;
if(y->ch[f]==x) rotate(x,!f);
else rotate(y,f);
rotate(x,f);
}
}
pushup(x);
}
node *access(node *u)
{
node *v=null;
while (u!=null)
{
splay(u);
v->p=u;
u->ch[1]=v;
pushup(u);
v=u;
u=u->p;
}
return v;
}
node *link(node *u,node *v)//合并
{
access(u);
splay(u);
u->rev=1;
u->p=v;
}
node *cut(node *u)//分离
{
access(u);
splay(u);
u->ch[0]=u->ch[0]->p=null;
pushup(u);
}
void changeroot(node *u)//换根
{
access(u)->rev^=1;
}
node *getroot(node *u)//找根
{
access(u);
splay(u);
while (u->p!=null) u=u->p;
splay(u);
return u;
}
bool queryuv(node *u,node *v)//判断是否在同一子树
{
while (u->p!=null) u=u->p;
while (v->p!=null) v=v->p;
return u==v;
}
}splay;
int eu[N],ev[N];
int main ()
{
while (scanf("%d",&n)!=-1)
{
init();
for(int i=1;i<n;i++)
scanf("%d%d",&eu[i],&ev[i]);
for(int i=1;i<=n;i++)
{
int a;
scanf("%d",&a);
newnode(a);
}
for(int i=1;i<n;i++)
scanf("%d",&m);
for(int i=1;i<=m;i++)
{
scanf("%d",&u);
if(u==1)
{
scanf("%d%d",&u,&v);
if(splay.queryuv(nodes+u,nodes+v))
{
printf("-1\n");
continue;
}
}
else if(u==2)
{
scanf("%d%d",&u,&v);
if(u==v || !splay.queryuv(nodes+u,nodes+v))
{
printf("-1\n");
continue;
}
splay.changeroot(nodes+u);
splay.cut(nodes+v);
}
else if(u==3)
{
scanf("%d%d%d",&w,&u,&v);
if(! splay.queryuv(nodes+u,nodes+v))
{
printf("-1\n");
continue;
}
splay.changeroot(nodes+u);
splay.access(nodes+v);
node *q=splay.getroot(nodes+v);
q->mx+=w;
q->val+=w;
}
else
{
scanf("%d%d",&u,&v);
if(! splay.queryuv(nodes+u,nodes+v))
{
printf("-1\n");
continue;
}
splay.changeroot(nodes+u);
splay.access(nodes+v);
printf("%d\n",splay.getroot(nodes+v)->mx);
}
}
printf("\n");
}
return 0;
}