bzoj 1036: [ZJOI2008]树的统计Count (树链剖分)
ps:这道题过的人真多啊
一道树剖的模板题
(好像还可以用lct做, 然而我并不会
代码如下
1 /************************************************************** 2 Problem: 1036 3 User: cminus 4 Language: C++ 5 Result: Accepted 6 Time:2380 ms 7 Memory:4052 kb 8 ****************************************************************/ 9 10 #include <cstdio> 11 #include <vector> 12 #include <algorithm> 13 #include <cstring> 14 using namespace std; 15 const int N = 30100; 16 #define ls (o << 1) 17 #define rs (ls + 1) 18 19 int n, w[N]; 20 int fa[N], size[N], hs[N], dep[N], top[N], pos[N], tot; 21 int maxn[N*4], sum[N*4], L, R; 22 vector < int > edge[N]; 23 24 inline void dfs1(int u, int d, int f){ 25 dep[u] = d; fa[u] = f; size[u] = 1; hs[u] = -1; 26 int tmp = 0; 27 for (int i = 0; i < edge[u].size(); i++){ 28 int &v = edge[u][i]; 29 if (v == f) continue; 30 dfs1(v, d + 1, u); 31 if (size[v] > tmp) 32 tmp = size[v], hs[u] = v; 33 size[u] += size[v]; 34 } 35 } 36 37 inline void dfs2(int u, int t){ 38 top[u] = t, pos[u] = ++tot; 39 if (hs[u] == -1) return ; 40 dfs2(hs[u], t); 41 for (int i = 0; i < edge[u].size(); i++){ 42 int &v = edge[u][i]; 43 if (v != hs[u] && v != fa[u]) 44 dfs2(v, v); 45 } 46 } 47 48 inline int getSum(int o, int l, int r){ 49 if (L <= l && r <= R) return sum[o]; 50 int mid = (l + r) >> 1, ans = 0; 51 if (L <= mid) ans += getSum(ls, l, mid); 52 if (R > mid) ans += getSum(rs, mid + 1, r); 53 return ans; 54 } 55 56 inline int getMax(int o, int l, int r){ 57 if (L <= l && r <= R) return maxn[o]; 58 int mid = l + r >> 1, ans = -0x3f3f3f3f; 59 if (L <= mid) ans = max(ans, getMax(ls, l, mid)); 60 if (R > mid) ans = max(ans, getMax(rs, mid + 1, r)); 61 return ans; 62 } 63 64 inline int getMax(int l, int r){ 65 L = l, R = r; 66 return getMax(1, 1, tot); 67 } 68 69 inline int getSum(int l, int r){ 70 L = l, R = r; 71 return getSum(1, 1, tot); 72 } 73 74 inline void queryMax(int u, int v){ 75 int f1 = top[u], f2 = top[v], ans = -0x3f3f3f3f; 76 while(f1 != f2){ 77 if (dep[f1] < dep[f2]) 78 swap(u, v), swap(f1, f2); 79 ans = max(ans, getMax(pos[f1], pos[u])); 80 u = fa[f1]; f1 = top[u]; 81 } 82 if (dep[u] > dep[v]) swap(u, v); 83 printf("%d\n", max(ans, getMax(pos[u], pos[v]))); 84 } 85 86 inline void querySum(int u, int v){ 87 int f1 = top[u], f2 = top[v], ans = 0; 88 while(f1 != f2){ 89 if (dep[f1] < dep[f2]) 90 swap(u, v), swap(f1, f2); 91 ans += getSum(pos[f1], pos[u]); 92 u = fa[f1]; f1 = top[u]; 93 } 94 if (dep[u] > dep[v]) swap(u, v); 95 printf("%d\n", ans + getSum(pos[u], pos[v])); 96 } 97 98 inline void modify(int o, int l, int r, int u, int a){ 99 if(l == r){ 100 sum[o] = maxn[o] = a; 101 return ; 102 } 103 int mid = l + r >> 1; 104 if (u <= mid) modify(ls, l, mid, u, a); 105 else modify(rs, mid + 1, r, u, a); 106 sum[o] = sum[ls] + sum[rs]; 107 maxn[o] = max(maxn[ls], maxn[rs]); 108 } 109 110 int main(){ 111 scanf("%d", &n); 112 for (int i = 1; i < n; i++){ 113 int x, y; scanf("%d %d", &x, &y); 114 edge[x].push_back(y); 115 edge[y].push_back(x); 116 } 117 for (int i = 1; i <= n; i++) scanf("%d", &w[i]); 118 dfs1(1, 1, -1); dfs2(1, 1); 119 for (int i = 1; i <= n; i++) 120 modify(1, 1, tot, pos[i], w[i]); 121 int q; scanf("%d", &q); 122 char str[10]; int x, y; 123 while(q--){ 124 scanf("%s%d%d", str, &x, &y); 125 if (!strcmp(str, "QMAX")) queryMax(x, y); 126 else if (*str == 'C') modify(1, 1, tot, pos[x], y); 127 else querySum(x, y); 128 } 129 return 0; 130 } 131