可以保证修改没有问题,换根出了问题,过了1、2、5
而且小数据换根也没问题。。就很奇葩
# include <iostream>
# include <algorithm>
# include <cstdio>
# include <cmath>
using namespace std;
typedef long long ll;
const int N = 5e5 + 5;
const int inf = 1e18;
typedef struct {
int x , y , next;
} Edge;
Edge edge[N];
int E = 0 , elast[N];
void add(int x , int y) {
E ++;
edge[E].x = x;
edge[E].y = y;
edge[E].next = elast[x];
elast[x] = E;
}
int f[N] , dep[N] , son[N] , siz[N] , W[N];
void dfs1(int x , int fa) {
dep[x] = dep[fa] + 1;
f[x] = fa;
siz[x] = 1;
int maxv = -1;
for (int i = elast[x] ; i ; i = edge[i].next) {
int y = edge[i].y;
if (y != fa) {
dfs1(y , x);
siz[x] += siz[y];
if (siz[y] > maxv) son[x] = y , maxv = siz[y];
}
}
}
int top[N] , id[N] , w[N] , Cnt = 0;
int n , m , x , y , z;
void dfs2(int x , int Top) {
id[x] = ++ Cnt;
w[Cnt] = W[x];
top[x] = Top;
if (!son[x]) return ;
dfs2(son[x] , Top);
for (int i = elast[x] ; i ; i = edge[i].next) {
int y = edge[i].y;
if (y != f[x] && y != son[x]) dfs2(y , y);
}
}
typedef struct {
int l , r , lazy , minv;
}Node;
Node tr[N * 4];
void pushup(int p) {
tr[p].minv = min(tr[p << 1].minv , tr[p << 1 | 1].minv);
}
void pushdown(int p) {
if (tr[p].lazy) {
tr[p << 1].lazy = tr[p << 1 | 1].lazy = tr[p << 1].minv = tr[p << 1 | 1].minv = tr[p].lazy;
tr[p].lazy = 0;
}
}
void build(int p , int x , int y) {
tr[p].l = x , tr[p].r = y;
if (x == y) {
tr[p].minv = w[x];
return ;
} else {
int mid = (x + y) >> 1;
build(p << 1 , x , mid) , build(p << 1 | 1 , mid + 1 , y);
pushup(p);
}
}
void modify(int p , int x , int y , int d) {
if (x <= tr[p].l && tr[p].r <= y) {
tr[p].lazy = tr[p].minv = d;
return ;
} else {
int mid = (tr[p].l + tr[p].r) >> 1;
pushdown(p);
if (x <= mid) modify(p << 1 , x , y , d);
if (y > mid) modify(p << 1 | 1 , x , y , d);
pushup(p);
}
}
int query(int p , int x , int y) {
if (x <= tr[p].l && tr[p].r <= y) return tr[p].minv;
else {
pushdown(p);
int minv = 0x3f3f3f3f , mid = (tr[p].l + tr[p].r) >> 1;
if (x <= mid) minv = min(minv , query(p << 1 , x , y));
if (y > mid) minv = min(minv , query(p << 1 | 1 , x , y));
return minv;
}
}
void change(int x , int y , int d) {
while (top[x] != top[y]) {
if (dep[top[x]] < dep[top[y]]) swap(x , y);
modify(1 , id[top[x]] , id[x] , d);
x = f[top[x]];
}
if (dep[x] > dep[y]) swap(x , y);
modify(1 , id[x] , id[y] , d);
}
int root;
int F[N][60];
int K;
void dfs_lca(int u , int fa) {
F[u][0] = fa;
for (int j = 1 ; ; j ++) {
F[u][j] = F[F[u][j - 1]][j - 1];
if (F[u][j] == 0) {
K = max(K , j - 1);
break;
}
}
for (int j = elast[u] ; j ; j = edge[j].next) {
int v = edge[j].y;
if (v != fa) dfs_lca(v , u);
}
}
int get_lca(int u , int v) {
if (u == v) return u;
if (dep[u] < dep[v]) swap(u , v);
for (int j = K ; j >= 0 ; j --) {
if (dep[F[u][j]] >= dep[v]) u = F[u][j];
}
if (u == v) return u;
for (int j = K ; j >= 0 ; j --) {
if (F[u][j] != F[v][j]) {
u = F[u][j] , v = F[v][j];
}
}
return F[u][0];
}
int main() {
cin >> n >> m;
K = log2(n);
for (int i = 1 ; i < n ; i ++) {
cin >> x >> y;
add(x , y) , add(y , x);
}
for (int i = 1 ; i <= n ; i ++) {
cin >> W[i];
}
cin >> root;
dfs1(root , 0);
dfs2(root , root);
dfs_lca(root , 0);
build(1 , 1 , n);
int ans = 0;
while (m --) {
int opt;
cin >> opt >> x;
if (opt == 1) {
root = x;
}
if (opt == 2) {
scanf("%d%d" , &y , &z);
change(x , y , z);
}
if (opt == 3) {
if (x == root) {
printf("%d\n" , query(1 , 1 , n));
continue;
}
if (get_lca(x , root) != x || get_lca(x , root) == root) {
printf("%d\n" , query(1 , id[x] , id[x] + siz[x] - 1));
continue;
}
if (get_lca(x , root) == x) {
int ans = 0;
for (int j = elast[x] ; j ; j = edge[j].next) {
int v = edge[j].y;
if (get_lca(v , root) == v) {
printf("%d\n" , min(query(1 , 1 , id[v]) , query(1 , id[v] + siz[v] , n)));
break;
}
}
}
}
}
return 0;
}