BZOJ1036: [ZJOI2008]树的统计Count
1036: [ZJOI2008]树的统计Count
Time Limit: 10 Sec Memory Limit: 162 MBSubmit: 20055 Solved: 8146
[Submit][Status][Discuss]
Description
一棵树上有n个节点,编号分别为1到n,每个节点都有一个权值w。我们将以下面的形式来要求你对这棵树完成
一些操作: I. CHANGE u t : 把结点u的权值改为t II. QMAX u v: 询问从点u到点v的路径上的节点的最大权值 I
II. 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
树链剖分模板题
1 #include <iostream> 2 #include <cstdio> 3 #include <cstring> 4 #include <cstdlib> 5 #include <algorithm> 6 #include <queue> 7 #include <vector> 8 #define min(a, b) ((a) < (b) ? (a) : (b)) 9 #define max(a, b) ((a) > (b) ? (a) : (b)) 10 #define abs(a) ((a) < 0 ? (-1 * (a)) : (a)) 11 inline void swap(int &a, int &b){int tmp = a;a = b;b = tmp;} 12 inline void read(int &x) 13 { 14 x = 0;char ch = getchar(), c = ch; 15 while(ch < '0' || ch > '9') c = ch, ch = getchar(); 16 while(ch <= '9' && ch >= '0') x = x * 10 + ch - '0', ch = getchar(); 17 if(c == '-') x = -x; 18 } 19 const int INF = 0x3f3f3f3f; 20 const int MAXN = 100000 + 10; 21 struct Edge 22 { 23 int u,v,nxt; 24 Edge(int _u, int _v, int _nxt){u = _u;v = _v;nxt = _nxt;} 25 Edge(){} 26 }edge[MAXN << 1]; 27 int head[MAXN], cnt; 28 inline void insert(int a, int b) 29 { 30 edge[++cnt] = Edge(a,b,head[a]); 31 head[a] = cnt; 32 } 33 int n,q,tim,w[MAXN],size[MAXN],top[MAXN],son[MAXN],deep[MAXN],fa[MAXN],tid[MAXN],rank[MAXN]; 34 void dfs1(int u) 35 { 36 size[u] = 1; 37 for(register int pos = head[u];pos;pos = edge[pos].nxt) 38 { 39 int v = edge[pos].v; 40 if(v == fa[u]) continue; 41 deep[v] = deep[u] + 1, fa[v] = u; 42 dfs1(v); 43 size[u] += size[v]; 44 if(son[u] == -1 || size[v] > size[son[u]]) son[u] = v; 45 } 46 } 47 void dfs2(int u, int tp) 48 { 49 top[u] = tp, tid[u] = ++ tim, rank[tim] = u; 50 if(son[u] == -1) return; 51 dfs2(son[u], tp); 52 for(register int pos = head[u];pos;pos = edge[pos].nxt) 53 { 54 int v = edge[pos].v; 55 if(v != son[u] && v != fa[u]) dfs2(v, v); 56 } 57 } 58 59 struct Node 60 { 61 int l,r,ma,sum,lazy; 62 Node(){l = r = ma = sum = lazy = 0;} 63 }node[MAXN << 2]; 64 65 Node merge(Node &a, Node &b) 66 { 67 Node re; 68 if(a.l == 0) return b; 69 else if(b.l == 0) return a; 70 re.l = a.l, re.r = b.r; 71 re.ma = max(a.ma, b.ma); 72 re.sum = a.sum + b.sum; 73 return re; 74 } 75 76 void pushup(Node &a, Node &l, Node &r) 77 { 78 if(a.lazy) 79 { 80 l.sum += (l.r - l.l + 1) * a.lazy; 81 r.sum += (r.r - r.l + 1) * a.lazy; 82 l.lazy += a.lazy; 83 r.lazy += a.lazy; 84 l.ma += a.lazy; 85 r.ma += a.lazy; 86 a.lazy = 0; 87 } 88 } 89 90 void build(int o = 1, int l = 1, int r = n) 91 { 92 node[o].l = l, node[o].r = r; 93 if(l == r) 94 { 95 node[o].ma = node[o].sum = w[rank[l]]; 96 return; 97 } 98 int mid = (l + r) >> 1; 99 build(o << 1, l, mid); 100 build(o << 1 | 1, mid + 1, r); 101 node[o] = merge(node[o << 1], node[o << 1 | 1]); 102 return; 103 } 104 105 void modify(int ll, int rr, int k, int o = 1) 106 { 107 pushup(node[o], node[o << 1], node[o << 1 | 1]); 108 if(ll <= node[o].l && rr >= node[o].r) 109 { 110 node[o].ma += k; 111 node[o].sum += (node[o].r - node[o].l + 1) * k; 112 node[o].lazy += k; 113 return; 114 } 115 int mid = (node[o].l + node[o].r) >> 1; 116 if(mid >= ll) modify(ll, rr, k, o << 1); 117 if(mid < rr) modify(ll, rr, k, o << 1 | 1); 118 node[o] = merge(node[o << 1], node[o << 1 | 1]); 119 return; 120 } 121 122 Node ask(int ll, int rr, int o = 1) 123 { 124 pushup(node[o], node[o << 1], node[o << 1 | 1]); 125 if(ll <= node[o].l && rr >= node[o].r) return node[o]; 126 Node a,b;a.l= -1, b.l = -1; 127 int mid = (node[o].l + node[o].r) >> 1; 128 if(mid >= ll) a = ask(ll, rr,o << 1); 129 if(mid < rr) b = ask(ll, rr, o << 1 | 1); 130 if(a.l == -1) return b; 131 else if(b.l == -1) return a; 132 else return merge(a, b); 133 } 134 135 Node find(int x, int y) 136 { 137 int f1 = top[x], f2 = top[y]; 138 Node tmp; 139 Node re; 140 while(f1 != f2) 141 { 142 if(deep[f1] < deep[f2]) swap(f1, f2), swap(x, y); 143 tmp = ask(tid[f1], tid[x]); 144 re = merge(re, tmp); 145 x = fa[f1];f1 = top[x]; 146 } 147 if(x == y) 148 { 149 tmp = ask(tid[x], tid[x]); 150 return merge(re, tmp); 151 } 152 if(deep[x] > deep[y]) swap(x, y); 153 tmp = ask(tid[x], tid[y]); 154 return merge(re, tmp); 155 } 156 157 char s[20]; 158 159 int main() 160 { 161 read(n); 162 for(register int i = 1;i < n;++ i) 163 { 164 int tmp1,tmp2,tmp3; 165 read(tmp1), read(tmp2); 166 insert(tmp1, tmp2), insert(tmp2, tmp1); 167 } 168 for(register int i = 1;i <= n;++ i) read(w[i]); 169 memset(son, -1, sizeof(son)); 170 dfs1(1); 171 dfs2(1, 1); 172 build(); 173 read(q);Node tmp; 174 for(register int i = 1;i <= q;++ i) 175 { 176 int tmp1,tmp2; 177 scanf("%s", s + 1);read(tmp1), read(tmp2); 178 if(s[1] == 'C') modify(tid[tmp1], tid[tmp1], tmp2 - w[tmp1]), w[tmp1] = tmp2; 179 else 180 { 181 tmp = find(tmp1, tmp2); 182 if(s[2] == 'M') printf("%d\n", tmp.ma); 183 else printf("%d\n", tmp.sum); 184 } 185 } 186 return 0; 187 }