3306: 树(线段树)
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; }