1. 更改一個點的點權
2. 求一個子樹的最小點權
3. 換根

# Code

``````#include <algorithm>
#include <cstdio>
using std::max;
using std::min;
const int maxn = 100010;
int q[maxn], ind = 0, l[maxn], r[maxn], n, m, root, val[maxn], deep[maxn],
fa[maxn][20];
int cnt = 0;
struct edge {
int to, next;
} e[maxn];
int last[maxn];
struct seg {
int l, r, mn;
} t[maxn << 2];
void insert(int x, int y) {
e[++cnt].to = y;
e[cnt].next = last[x];
last[x] = cnt;
}
void update(int k) { t[k].mn = min(t[k << 1].mn, t[k << 1 | 1].mn); }
void dfs(int x) {
l[x] = ++ind;
q[ind] = x;
for (int i = 1; i <= 16; i++) {
if (deep[x] < (1 << i))
break;
fa[x][i] = fa[fa[x][i - 1]][i - 1];
}
for (int i = last[x]; i; i = e[i].next) {
fa[e[i].to][0] = x;
deep[e[i].to] = deep[x] + 1;
dfs(e[i].to);
}
r[x] = ind;
}
void build(int k, int l, int r) {
t[k].l = l, t[k].r = r;
int mid = (l + r) >> 1;
if (l == r) {
t[k].mn = val[q[l]];
return;
}
build(k << 1, l, mid);
build(k << 1 | 1, mid + 1, r);
t[k].mn = min(t[k << 1].mn, t[k << 1 | 1].mn);
}
void modify(int k, int pos, int val) {
int l = t[k].l, r = t[k].r, mid = (l + r) >> 1;
if (l == r) {
t[k].mn = val;
return;
}
if (pos <= mid)
modify(k << 1, pos, val);
else
modify(k << 1 | 1, pos, val);
update(k);
}
int query(int k, int x, int y) {
int l = t[k].l, r = t[k].r, mid = (l + r) >> 1;
if (x <= l && r <= y)
return t[k].mn;
int ans = 0x3f3f3f;
if (x <= mid)
ans = min(ans, query(k << 1, x, y));
if (y > mid)
ans = min(ans, query(k << 1 | 1, x, y));
return ans;
}
int main() {
#ifndef ONLINE_JUDGE
freopen("input", "r", stdin);
#endif
scanf("%d %d", &n, &m);
for (int i = 1; i <= n; i++) {
int f;
scanf("%d %d", &f, &val[i]);
if (f)
insert(f, i);
}
dfs(root = 1);
#ifndef ONLINE_JUDGE
for (int i = 1; i <= ind; i++)
printf("%d ", q[i]);
printf("\n");
#endif
build(1, 1, n);
while (m--) {
char ch[5];
int x;
scanf("%s %d", ch, &x);
if (ch[0] == 'V') {
int val;
scanf("%d", &val);
modify(1, l[x], val);
} else if (ch[0] == 'E')
root = x;
else {
if (root == x)
printf("%d\n", t[1].mn);
else if (l[x] <= l[root] && r[x] >= r[root]) { // x is the father of root
int y = root, d = deep[y] - deep[x] - 1;
for (int i = 0; i <= 16; i++)
if (d & (1 << i))
y = fa[y][i];
printf("%d\n", min(query(1, 1, l[y] - 1), query(1, r[y] + 1, n)));
} else
printf("%d\n", query(1, l[x], r[x]));
}
}
return 0;
}``````