【BZOJ1036】【树链剖分】树的统计Count
Description
一 棵树上有n个节点,编号分别为1到n,每个节点都有一个权值w。我们将以下面的形式来要求你对这棵树完成一些操作: I. CHANGE u t : 把结点u的权值改为t II. QMAX u v: 询问从点u到点v的路径上的节点的最大权值 III. QSUM u v: 询问从点u到点v的路径上的节点的权值和 注意:从点u到点v的路径上的节点包括u和v本身
Input
输 入的第一行为一个整数n,表示节点的个数。接下来n – 1行,每行2个整数a和b,表示节点a和节点b之间有一条边相连。接下来n行,每行一个整数,第i行的整数wi表示节点i的权值。接下来1行,为一个整数 q,表示操作的总数。接下来q行,每行一个操作,以“CHANGE u t”或者“QMAX u v”或者“QSUM u v”的形式给出。 对于100%的数据,保证1<=n<=30000,0<=q<=200000;中途操作中保证每个节点的权值w在-30000到 30000之间。
Output
对于每个“QMAX”或者“QSUM”的操作,每行输出一个整数表示要求输出的结果。
Sample Input
4
1 2
2 3
4 1
4 2 1 3
12
QMAX 3 4
QMAX 3 3
QMAX 3 2
QMAX 2 3
QSUM 3 4
QSUM 2 1
CHANGE 1 5
QMAX 3 4
CHANGE 3 6
QMAX 3 4
QMAX 2 4
QSUM 3 4
1 2
2 3
4 1
4 2 1 3
12
QMAX 3 4
QMAX 3 3
QMAX 3 2
QMAX 2 3
QSUM 3 4
QSUM 2 1
CHANGE 1 5
QMAX 3 4
CHANGE 3 6
QMAX 3 4
QMAX 2 4
QSUM 3 4
Sample Output
4
1
2
2
10
6
5
6
5
16
1
2
2
10
6
5
6
5
16
HINT
Source
【分析】
SB题,不说了。
1 /* 2 唐代李白 3 《南陵别儿童入京》 4 白酒新熟山中归,黄鸡啄黍秋正肥。 5 呼童烹鸡酌白酒,儿女嬉笑牵人衣。 6 高歌取醉欲自慰,起舞落日争光辉。 7 游说万乘苦不早,著鞭跨马涉远道。 8 会稽愚妇轻买臣,余亦辞家西入秦。 9 仰天大笑出门去,我辈岂是蓬蒿人。 10 */ 11 #include <iostream> 12 #include <cstdio> 13 #include <algorithm> 14 #include <cstring> 15 #include <vector> 16 #include <utility> 17 #include <iomanip> 18 #include <string> 19 #include <cmath> 20 #include <queue> 21 #include <assert.h> 22 #include <map> 23 #include <ctime> 24 #include <cstdlib> 25 #include <stack> 26 #define LOCAL 27 const int INF = 0x3f3f3f3f; 28 const int MAXN = 100000 + 10; 29 const int maxnode = 1000000; 30 const int maxm= 30000 * 2 + 10; 31 using namespace std; 32 struct Node{ 33 int l, r; 34 int Max, sum; 35 Node *ch[2]; 36 }*root, mem[maxnode]; 37 struct Edge{ 38 int u, v; 39 }edge[MAXN]; 40 41 int n, top[MAXN], fa[MAXN]; 42 int dep[MAXN], size[MAXN], son[MAXN]; 43 int head[MAXN], next[MAXN], to[MAXN]; 44 int pos[MAXN], Time, M, tot; 45 46 void dfs_1(int u){ 47 size[u] = 1; 48 son[u] = 0; 49 for (int i = head[u]; i != -1; i = next[i]){ 50 int v = to[i]; 51 if (v == fa[u]) continue; 52 fa[v] = u; 53 dep[v] = dep[u] + 1; 54 dfs_1(v); 55 size[u] += size[v]; 56 if (size[v] > size[son[u]]) son[u] = v; 57 } 58 } 59 //标号 60 void dfs_2(int u, int top_node){ 61 top[u] = top_node; 62 pos[u] = ++Time;//这里就不是代表边了,而是点 63 if (son[u]) dfs_2(son[u], top_node); 64 65 for (int i = head[u]; i != -1; i = next[i]){ 66 int v = to[i]; 67 if (v == fa[u] || v == son[u]) continue; 68 dfs_2(v, v); 69 } 70 } 71 void addEdge(int u, int v){ 72 to[M] = v; 73 next[M] = head[u]; 74 head[u] = M++; 75 } 76 Node *NEW(int l, int r){ 77 Node *p = &mem[tot++]; 78 p->l = l; 79 p->r = r; 80 p->Max = p->sum = 0; 81 return p; 82 } 83 //连区间修改都没有 84 void update(Node *&t){ 85 if (t->l == t->r) return; 86 t->Max = max(t->ch[0]->Max, t->ch[1]->Max); 87 t->sum = t->ch[1]->sum + t->ch[0]->sum; 88 } 89 void build(Node *&t, int l, int r){ 90 if (t == NULL){ 91 t = NEW(l, r); 92 } 93 if (l == r) return; 94 int mid = (l + r) >> 1; 95 build(t->ch[0], l, mid); 96 build(t->ch[1], mid + 1, r); 97 } 98 void change(Node *&t, int l, int x){ 99 if (t->l == l && t->r == l){ 100 t->sum = t->Max = x; 101 return; 102 } 103 int mid = (t->l + t->r) >> 1; 104 if (l <= mid) change(t->ch[0], l, x); 105 else change(t->ch[1], l, x); 106 107 update(t); 108 } 109 void init(){ 110 memset(dep, 0, sizeof(dep)); 111 memset(head, -1, sizeof(head)); 112 113 M = Time = tot = 0; 114 scanf("%d", &n); 115 for (int i = 1; i < n; i++){ 116 scanf("%d%d", &edge[i].u, &edge[i].v); 117 addEdge(edge[i].u, edge[i].v); 118 addEdge(edge[i].v, edge[i].u); 119 } 120 fa[1] = 0; 121 size[0] = 0; 122 123 dfs_1(1); 124 dfs_2(1, 1); 125 root = NULL; 126 build(root, 1, Time); 127 //因为不是边所以跟父亲没什么关系,不用对边进行更新 128 for (int i = 1; i <= n; i++){ 129 int t; 130 scanf("%d", &t); 131 change(root, pos[i], t); 132 } 133 //printf("%d\n", root->Max); 134 } 135 int query_sum(Node *&t, int l, int r){ 136 if (l <= t->l && t->r <= r) return t->sum; 137 int mid = (t->l + t->r) >> 1; 138 int cnt = 0; 139 if (l <= mid) cnt += query_sum(t->ch[0], l, r); 140 if (r > mid) cnt += query_sum(t->ch[1], l, r); 141 return cnt; 142 } 143 int query_max(Node *&t, int l, int r){ 144 if (l <= t->l && t->r <= r) return t->Max; 145 int mid = (t->l + t->r) >> 1; 146 int Ans = -INF; 147 if (l <= mid) Ans = max(Ans, query_max(t->ch[0], l, r)); 148 if (r > mid) Ans = max(Ans, query_max(t->ch[1], l, r)); 149 return Ans; 150 } 151 int QMAX(int l, int r){ 152 int Ans = -INF; 153 while (top[l] != top[r]){ 154 //低的往上爬 155 if (dep[top[l]] < dep[top[r]]) swap(l, r); 156 Ans = max(Ans, query_max(root, pos[top[l]], pos[l])); 157 l = fa[top[l]]; 158 } 159 //if (l == r) return Ans; 160 if (dep[l] > dep[r]) swap(l, r); 161 Ans = max(Ans, query_max(root, pos[l], pos[r])); 162 return Ans; 163 } 164 int QSUM(int l, int r){ 165 int sum = 0; 166 while (top[l] != top[r]){ 167 //低的往上爬 168 if (dep[top[l]] < dep[top[r]]) swap(l, r); 169 sum += query_sum(root, pos[top[l]], pos[l]); 170 l = fa[top[l]]; 171 } 172 //if (l == r) return sum; 173 if (dep[l] > dep[r]) swap(l, r); 174 sum += query_sum(root, pos[l], pos[r]); 175 return sum; 176 } 177 void work(){ 178 int q; 179 scanf("%d", &q); 180 for (int i = 1; i <= q; i++){ 181 char str[10]; 182 scanf("%s", str); 183 if (str[0] == 'C'){ 184 int l, x; 185 scanf("%d%d", &l, &x); 186 change(root, pos[l], x); 187 }else{ 188 if (str[1] == 'M'){ 189 int l, r; 190 scanf("%d%d", &l, &r); 191 printf("%d\n", QMAX(l, r)); 192 }else{ 193 int l, r; 194 scanf("%d%d", &l, &r); 195 printf("%d\n", QSUM(l, r)); 196 } 197 } 198 } 199 } 200 201 int main(){ 202 int T; 203 204 init(); 205 work(); 206 return 0; 207 }