#include "bits/stdc++.h"
using namespace std;
#define MAXN 101000
struct EDGE{
int Next,To;
}E[MAXN<<1];
unsigned int Head[MAXN<<1],Size;
inline void Add(int From,int To){
E[++Size].Next=Head[From];
Head[From]=Size;
E[Size].To=To;
return;
}
unsigned int Dep[MAXN],Fa[MAXN];
unsigned int Tot[MAXN],Son[MAXN];
inline void DFS1(int This,int F){
Fa[This]=F;
Tot[This]=1;
int MaxSon=0;
Dep[This]=Dep[F]+1;
for(register int i=Head[This];i;i=E[i].Next){
int To=E[i].To;
if(To==F)continue;
DFS1(To,This);
Tot[This]+=Tot[To];
if(MaxSon<Tot[To]){
MaxSon=Tot[To];
Son[This]=To;
}
}
return;
}
unsigned int A[MAXN],InPut[MAXN];
unsigned int Top[MAXN],ID[MAXN],Count;
inline void DFS2(int This,int Topf){
Top[This]=Topf;
ID[This]=(++Count);
InPut[Count]=A[This];
if(Son[This]==0)
return;
DFS2(Son[This],Topf);
for(register int i=Head[This];i;i=E[i].Next){
int To=E[i].To;
if(To==Fa[This]||To==Son[This])
continue;
DFS2(To,To);
}
return;
}
struct NPC{
struct SegmentTree{
unsigned int Left,Right;
unsigned int Lazy,Num;
}Tree[MAXN<<2];
inline int LeftSon(int i){return i<<1;}
inline int RightSon(int i){return i<<1|1;}
inline void Tree_Build(int i,int Left,int Right){
Tree[i].Left=Left;
Tree[i].Right=Right;
if(Left==Right){
Tree[i].Num=InPut[Left];
return;
}
unsigned int Mid=(Left+Right)>>1;
unsigned int L=LeftSon(i),R=RightSon(i);
Tree_Build(L,Left,Mid);
Tree_Build(R,Mid+1,Right);
Tree[i].Num=min(Tree[L].Num,Tree[R].Num);
return;
}
inline void PushDown(int i){
if(Tree[i].Lazy==0)
return;
unsigned int L=LeftSon(i),R=RightSon(i);
Tree[L].Lazy=Tree[R].Lazy=Tree[i].Lazy;
Tree[L].Num=Tree[R].Num=Tree[i].Lazy;
Tree[i].Lazy=0;
return;
}
inline void AddSeg(int i,int Left,int Right,int Add){
if(Tree[i].Right<Left||Right<Tree[i].Left)
return;
if(Left<=Tree[i].Left&&Tree[i].Right<=Right){
Tree[i].Lazy=Add;
Tree[i].Num=Add;
return;
}
PushDown(i);
unsigned int L=LeftSon(i),R=RightSon(i);
if(Tree[L].Right>=Left)AddSeg(L,Left,Right,Add);
if(Tree[R].Left<=Right)AddSeg(R,Left,Right,Add);
Tree[i].Num=min(Tree[L].Num,Tree[R].Num);
return;
}
#define INF 2147483648
inline unsigned int MinSeg(int i,int Left,int Right){
if(Tree[i].Right<Left||Right<Tree[i].Left)
return INF;
if(Left<=Tree[i].Left&&Tree[i].Right<=Right)
return Tree[i].Num;
PushDown(i);
unsigned int Min=INF,L=LeftSon(i),R=RightSon(i);
if(Tree[L].Right>=Left)Min=min(Min,MinSeg(L,Left,Right));
if(Tree[R].Left<=Right)Min=min(Min,MinSeg(R,Left,Right));
return Min;
}
}Do;
inline void Cover(int X,int Y,unsigned int Z){
while(Top[X]!=Top[Y]){
if(Dep[Top[X]]<Dep[Top[Y]])
swap(X,Y);
Do.AddSeg(1,ID[Top[X]],ID[X],Z);
X=Fa[Top[X]];
}
if(Dep[X]>Dep[Y])
swap(X,Y);
Do.AddSeg(1,ID[X],ID[Y],Z);
return;
}
inline int Find(int F,int This){
while(Top[This]!=Top[F]){
if(Fa[Top[This]]==F)
return Top[This];
This=Fa[Top[This]];
}
return Son[F];
}
unsigned int Root,Tmp,SR;
unsigned int N,M,X,Y,Z,D;
int main(void){
scanf("%d%d",&N,&M);
for(register int i=1;i<N;i++){
scanf("%d%d",&X,&Y);
Add(X,Y),Add(Y,X);
}
for(register int i=1;i<=N;i++)
scanf("%d",&A[i]);
scanf("%d",&Root);
DFS1(Root,0);
DFS2(Root,Root);
Do.Tree_Build(1,1,N);
for(register int i=1;i<=M;i++){
scanf("%d",&D);
if(D==1)scanf("%d",&Root);
else if(D==2){
scanf("%d%d%d",&X,&Y,&Z);
Cover(X,Y,Z);
}
else if(D==3){
scanf("%d",&X);
if(ID[Root]==ID[X])
printf("%d\n",Do.MinSeg(1,1,N));
#define SumSon (ID[X]+Tot[X]-1)
else if(ID[Root]<ID[X]||ID[Root]>SumSon)
printf("%d\n",Do.MinSeg(1,ID[X],SumSon));
else if(ID[X]<ID[Root]&&ID[Root]<=SumSon){
Tmp=INF,SR=Find(X,Root);
Tmp=min(Tmp,Do.MinSeg(1,ID[SR]+Tot[SR],N));
Tmp=min(Tmp,Do.MinSeg(1,1,ID[X]));
printf("%d\n",Tmp);
}
}
}
return 0;
}
第六第十个点WA