应该是个已经做烂了的经典套路题
虽然题目要求换根
但是实际上并不需要
只要分情况讨论即可
如果查询的(x=root)直接查询整颗树
如果(x)是(root)的祖先相当于把整颗树拎起来
查询的实际上是整颗树除了(root)所在的以(x)的儿子为根节点的子树的部分
否则查询的还是(x)的子树
具体可以想象一下(root)和(x)的情况,想象一下把从(root)整颗树拎起来会变成什么样
然后就是树剖板子了
#include<bits/stdc++.h>
using namespace std;
#define gc c=getchar()
#define r(x) read(x)
#define ls (rt<<1)
#define rs (rt<<1|1)
template<typename T>
inline void read(T&x){
x=0;T k=1;char gc;
while(!isdigit(c)){if(c=='-')k=-1;gc;}
while(isdigit(c)){x=x*10+c-'0';gc;}x*=k;
}
const int N=100005;
vector<int> G[N];
int ac[N][20],dep[N],siz[N],son[N];
void dfs1(int x,int f){
ac[x][0]=f;
dep[x]=dep[f]+1;
siz[x]=1;
for(int i=1;(ac[x][i]=ac[ac[x][i-1]][i-1]);++i);
for(int i=0;i<G[x].size();++i){
int v=G[x][i];
if(v==f)continue;
dfs1(v,x);
siz[x]+=siz[v];
if(siz[v]>siz[son[x]])son[x]=v;
}
}
int top[N],dfn[N],ptn[N],dfs_clock;
void dfs2(int x,int t){
top[x]=t;
dfn[x]=++dfs_clock;
ptn[dfs_clock]=x;
if(son[x])dfs2(son[x],t);
for(int i=0;i<G[x].size();++i){
int v=G[x][i];
if((v==ac[x][0])||(v==son[x]))continue;
dfs2(v,v);
}
}
inline int find(int x,int t){
for(int i=17;~i;--i){
if(dep[x]-dep[t]>(1<<i))x=ac[x][i];
}
assert(ac[x][0]==t);
return x;
}
struct Seg{
int min,tag;
}tr[N<<2];
int a[N];
inline void update(int rt){
tr[rt].min=min(tr[ls].min,tr[rs].min);
}
inline void pushdown(int rt){
if(tr[rt].tag){
tr[ls].min=tr[rs].min=tr[ls].tag=tr[rs].tag=tr[rt].tag;
tr[rt].tag=0;
}
}
void build(int rt,int l,int r){
if(l==r){
tr[rt].min=a[ptn[l]];
return ;
}
int mid=(l+r)>>1;
build(ls,l,mid);
build(rs,mid+1,r);
update(rt);
}
void modify(int rt,int l,int r,int x,int y,int v){
if(x<=l&&r<=y){
tr[rt].min=tr[rt].tag=v;
return ;
}
pushdown(rt);
int mid=(l+r)>>1;
if(x<=mid)modify(ls,l,mid,x,y,v);
if(y>mid)modify(rs,mid+1,r,x,y,v);
update(rt);
}
int query(int rt,int l,int r,int x,int y){
if(x>y)return 1e9;
if(x<=l&&r<=y)return tr[rt].min;
pushdown(rt);
int mid=(l+r)>>1;
if(y<=mid)return query(ls,l,mid,x,y);
else if(x>mid)return query(rs,mid+1,r,x,y);
else return min(query(ls,l,mid,x,y),query(rs,mid+1,r,x,y));
}
int root,n,m;
inline void modify(int u,int v,int w){
while(top[u]!=top[v]){
if(dep[top[u]]<dep[top[v]])swap(u,v);
modify(1,1,n,dfn[top[u]],dfn[u],w);
u=ac[top[u]][0];
}
if(dep[u]>dep[v])swap(u,v);
modify(1,1,n,dfn[u],dfn[v],w);
return ;
}
inline int query(int x){
if(x==root)return query(1,1,n,1,n);
if(dfn[x]<dfn[root]&&dfn[root]<dfn[x]+siz[x]){
int t=find(root,x);
return min(query(1,1,n,1,dfn[t]-1),query(1,1,n,dfn[t]+siz[t],n));
}
return query(1,1,n,dfn[x],dfn[x]+siz[x]-1);
}
int main(){
r(n),r(m);
for(int i=1,u,v;i<n;++i){
r(u),r(v);
G[u].push_back(v);
G[v].push_back(u);
}
for(int i=1;i<=n;++i)r(a[i]);
r(root);
dfs1(1,0);
dfs2(1,1);
build(1,1,n);
for(int i=1,opt,l,r,x;i<=m;++i){
r(opt);
if(opt==1)r(root);
else if(opt==2){
r(l),r(r),r(x);
modify(l,r,x);
}
else {
r(x);
printf("%d
",query(x));
}
}
}