A:
树剖板子题
求最小值的时候要注意值是不是有负数,如果有,初值要置为$-INF$
1 #include <bits/stdc++.h> 2 using namespace std; 3 4 #define N 30010 5 #define INF 0x3f3f3f3f 6 int n, q, arr[N]; 7 vector <int> G[N]; 8 9 int fa[N], deep[N], sze[N], son[N], top[N], p[N], fp[N], cnt; 10 void DFS(int u) 11 { 12 sze[u] = 1; 13 for (auto v : G[u]) if (v != fa[u]) 14 { 15 fa[v] = u; 16 deep[v] = deep[u] + 1; 17 DFS(v); 18 sze[u] += sze[v]; 19 if (!son[u] || sze[v] > sze[son[u]]) son[u] = v; 20 } 21 } 22 23 void getpos(int u, int sp) 24 { 25 top[u] = sp; 26 p[u] = ++cnt; 27 fp[cnt] = u; 28 if (!son[u]) return; 29 getpos(son[u], sp); 30 for (auto v : G[u]) if (v != fa[u] && v != son[u]) 31 getpos(v, v); 32 } 33 34 namespace SEG 35 { 36 struct node 37 { 38 int Max, sum; 39 node () {} 40 node (int Max, int sum) : Max(Max), sum(sum) {} 41 node operator + (const node &other) const { return node(max(Max, other.Max), sum + other.sum); } 42 }a[N << 2], res; 43 void build(int id, int l, int r) 44 { 45 if (l == r) 46 { 47 a[id] = node(arr[fp[l]], arr[fp[l]]); 48 return; 49 } 50 int mid = (l + r) >> 1; 51 build(id << 1, l, mid); 52 build(id << 1 | 1, mid + 1, r); 53 a[id] = a[id << 1] + a[id << 1 | 1]; 54 } 55 void update(int id, int l, int r, int pos, int val) 56 { 57 if (l == r) 58 { 59 a[id] = node(val, val); 60 return; 61 } 62 int mid = (l + r) >> 1; 63 if (pos <= mid) update(id << 1, l, mid, pos, val); 64 else update(id << 1 | 1, mid + 1, r, pos, val); 65 a[id] = a[id << 1] + a[id << 1 | 1]; 66 } 67 void query(int id, int l, int r, int ql, int qr) 68 { 69 if (l >= ql && r <= qr) 70 { 71 res = res + a[id]; 72 return; 73 } 74 int mid = (l + r) >> 1; 75 if (ql <= mid) query(id << 1, l, mid, ql, qr); 76 if (qr > mid) query(id << 1 | 1, mid + 1, r, ql, qr); 77 } 78 } 79 80 void query(int u, int v) 81 { 82 while (top[u] != top[v]) 83 { 84 if (deep[top[u]] < deep[top[v]]) swap(u, v); 85 SEG::query(1, 1, n, p[top[u]], p[u]); 86 u = fa[top[u]]; 87 } 88 if (deep[u] > deep[v]) swap(u, v); 89 SEG::query(1, 1, n, p[u], p[v]); 90 } 91 92 int main() 93 { 94 while (scanf("%d%d", &n, &q) != EOF) 95 { 96 cnt = 0; 97 memset(son, 0, sizeof son); 98 for (int i = 1; i <= n; ++i) scanf("%d", arr + i), G[i].clear(); 99 for (int i = 1, u, v; i < n; ++i) 100 { 101 scanf("%d%d", &u, &v); 102 G[u].push_back(v); 103 G[v].push_back(u); 104 } 105 DFS(1); getpos(1, 1); SEG::build(1, 1, n); 106 for (int i = 1, op, x, y; i <= q; ++i) 107 { 108 scanf("%d%d%d", &op, &x, &y); 109 if (op == 2) SEG::update(1, 1, n, p[x], y); 110 else 111 { 112 SEG::res = SEG::node(-INF, 0); 113 query(x, y); 114 printf("%d\n", op == 0 ? SEG::res.Max : SEG::res.sum); 115 } 116 } 117 } 118 return 0; 119 }