1.思路
首先dfs整颗树将树转换线性结构,前两个操作比较简单,然后主要是对于操作三,有三种情况:
1.x=rt,那么我们直接求出整颗树中的最小值就是答案;
2.x在原树中为rt的祖先节点,那么我们首先求出从x到rt路径上的x的第一个节点y,那么答案就是除了以y为根的子树的其他所有节点的最小值;
3.对于除了以上两种情况,直接求出以x为根的子树的最小值即为答案.
2.代码
#include <bits/stdc++.h>
using namespace std;
const int N = 2e5+5;
#define ls rt<<1
#define rs rt<<1|1
struct Edge{
int to, next;
};
Edge e[N];
int head[N];
int dep[N];
int tot;
void addEdge(int u, int v) {
e[++tot] = Edge{v, head[u]};
head[u] = tot;
}
int a[N], b[N];
int l[N], r[N];
int dfs_clock;
int f[N][20];
void dfs(int u) {
l[u] = ++ dfs_clock;
a[dfs_clock] = b[u];
for(int i = head[u]; i; i = e[i].next) {
int to = e[i].to;
dep[to] = dep[u] + 1;
f[to][0] = u;
dfs(to);
}
r[u] = dfs_clock;
}
int v[N<<2];
inline void pushUp(int rt) {
v[rt] = v[ls] < v[rs]? v[ls] : v[rs];
}
void build(int rt, int l, int r) {
if(l == r) {
v[rt] = a[l];
return ;
}
int mid = (l + r) >> 1;
build(ls, l, mid);
build(rs, mid+1, r);
pushUp(rt);
}
void update(int rt, int l, int r, int a, int b) {
if(l == r) {
v[rt] = b;
return ;
}
int mid = (l + r) >> 1;
if(a <= mid) {
update(ls, l, mid, a, b);
}
else {
update(rs, mid+1, r, a, b);
}
pushUp(rt);
}
int query(int rt, int l, int r, int a, int b) {
if(a > b) return INT_MAX;
if(a <= l && r <= b) {
return v[rt];
}
int mid = (l + r) >> 1;
int res = INT_MAX;
if(a <= mid) {
res = min(res, query(ls, l, mid, a, b));
}
if(b > mid) {
res = min(res, query(rs, mid+1, r, a, b));
}
return res;
}
void initLca(int n) {
for(int j = 1; j < 20; ++ j) {
for(int i = 1; i <= n; ++ i) {
f[i][j] = f[f[i][j-1]][j-1];
}
}
}
int go(int x, int d) {
for(int i = 0; i < 20; ++ i) {
if(d&(1<<i)) {
x = f[x][i];
}
}
return x;
}
int main() {
int n, m;
scanf("%d%d", &n, &m);
int rt;
for(int i = 1; i <= n; ++ i) {
int x;
scanf("%d%d", &x, &b[i]);
if(x == 0) rt = i;
else addEdge(x, i);
}
dfs(rt);
build(1, 1, n);
initLca(n);
while(m --) {
char op[5];
scanf("%s", op);
if(op[0] == 'Q') {
int x;
scanf("%d", &x);
if(x == rt) {
printf("%d\n", v[1]);
}
/* error
else if(dep[x] > dep[rt]) {
int res = query(1, 1, n, l[x], r[x]);
printf("%d\n", res);
}
*/
else if(l[x] < l[rt] && r[x] >= r[rt]) {
int di = dep[rt] - dep[x] - 1;
int y = go(rt, di);
int res = query(1, 1, n, 1, l[y]-1);
res = min(res, query(1, 1, n, r[y]+1, n));
printf("%d\n", res);
}
else {
int res = query(1, 1, n, l[x], r[x]);
printf("%d\n", res);
}
}
else if(op[0] == 'V'){
int x, y;
scanf("%d%d", &x, &y);
update(1, 1, n, l[x], y);
}
else {
scanf("%d", &rt);
}
}
return 0;
}