Problem Description
We have met so many problems on the tree, so today we will have a query problem on a set of trees.
There are N nodes, each node will have a unique weight Wi. We will have four kinds of operations on it and you should solve them efficiently. Wish you have fun!
There are N nodes, each node will have a unique weight Wi. We will have four kinds of operations on it and you should solve them efficiently. Wish you have fun!
Input
There are multiple test cases in our dataset.
For each case, the first line contains only one integer N.(1 ≤ N ≤ 300000) The next N‐1 lines each contains two integers x, y which means there is an edge between them. It also means we will give you one tree initially.
The next line will contains N integers which means the weight Wi of each node. (0 ≤ Wi ≤ 3000)
The next line will contains an integer Q. (1 ≤ Q ≤ 300000) The next Q lines will start with an integer 1, 2, 3 or 4 means the kind of this operation.
1. Given two integer x, y, you should make a new edge between these two node x and y. So after this operation, two trees will be connected to a new one.
2. Given two integer x, y, you should find the tree in the tree set who contain node x, and you should make the node x be the root of this tree, and then you should cut the edge between node y and its parent. So after this operation, a tree will be separate into two parts.
3. Given three integer w, x, y, for the x, y and all nodes between the path from x to y, you should increase their weight by w.
4. Given two integer x, y, you should check the node weights on the path between x and y, and you should output the maximum weight on it.
For each case, the first line contains only one integer N.(1 ≤ N ≤ 300000) The next N‐1 lines each contains two integers x, y which means there is an edge between them. It also means we will give you one tree initially.
The next line will contains N integers which means the weight Wi of each node. (0 ≤ Wi ≤ 3000)
The next line will contains an integer Q. (1 ≤ Q ≤ 300000) The next Q lines will start with an integer 1, 2, 3 or 4 means the kind of this operation.
1. Given two integer x, y, you should make a new edge between these two node x and y. So after this operation, two trees will be connected to a new one.
2. Given two integer x, y, you should find the tree in the tree set who contain node x, and you should make the node x be the root of this tree, and then you should cut the edge between node y and its parent. So after this operation, a tree will be separate into two parts.
3. Given three integer w, x, y, for the x, y and all nodes between the path from x to y, you should increase their weight by w.
4. Given two integer x, y, you should check the node weights on the path between x and y, and you should output the maximum weight on it.
Output
For each query you should output the correct answer of it. If you find this query is an illegal operation, you should output ‐1.
You should output a blank line after each test case.
You should output a blank line after each test case.
题目大意:给出一棵带点权树,有4种操作:连边x到y;删掉以x为根的树种y与其父节点的连边;把x到y路径上所有点的权值+1;询问x到y路径上的最大点权。
推荐论文:《QTREE解法的一些研究》,参考代码:http://www.cnblogs.com/kuangbin/archive/2013/09/04/3300251.html
代码(1156MS):
1 #include <cstdio> 2 #include <iostream> 3 #include <algorithm> 4 #include <cstring> 5 using namespace std; 6 7 const int MAXN = 300010; 8 const int MAXE = MAXN * 2; 9 const int INF = 0x7fffffff; 10 11 int ch[MAXN][2], pre[MAXN], key[MAXN]; 12 int add[MAXN], rev[MAXN], maxt[MAXN]; 13 bool rt[MAXN]; 14 15 int head[MAXN]; 16 int to[MAXE], next[MAXE]; 17 int ecnt, n, m, op; 18 19 inline void init() { 20 ecnt = 2; 21 for(int i = 0; i <= n; ++i) { 22 head[i] = ch[i][0] = ch[i][1] = 0; 23 pre[i] = add[i] = rev[i] = 0; 24 rt[i] = true; 25 } 26 maxt[0] = -INF; 27 } 28 29 inline void add_edge(int u, int v) { 30 to[ecnt] = v; next[ecnt] = head[u]; head[u] = ecnt++; 31 to[ecnt] = u; next[ecnt] = head[v]; head[v] = ecnt++; 32 } 33 34 void dfs(int u) { 35 for(int p = head[u]; p; p = next[p]) { 36 int &v = to[p]; 37 if(pre[v]) continue; 38 pre[v] = u; 39 dfs(v); 40 } 41 } 42 43 inline void update_max(int r) { 44 maxt[r] = max(max(maxt[ch[r][0]], maxt[ch[r][1]]), key[r]); 45 } 46 47 inline void update_add(int r, int d) { 48 if(!r) return ; 49 key[r] += d; 50 maxt[r] += d; 51 add[r] += d; 52 } 53 54 inline void update_rev(int r) { 55 if(!r) return ; 56 swap(ch[r][0], ch[r][1]); 57 rev[r] ^= 1; 58 } 59 60 inline void pushdown(int r) { 61 if(add[r]) { 62 update_add(ch[r][0], add[r]); 63 update_add(ch[r][1], add[r]); 64 add[r] = 0; 65 } 66 if(rev[r]) { 67 update_rev(ch[r][0]); 68 update_rev(ch[r][1]); 69 rev[r] = 0; 70 } 71 } 72 73 void rotate(int x) { 74 int y = pre[x], t = ch[y][1] == x; 75 ch[y][t] = ch[x][!t]; 76 pre[ch[y][t]] = y; 77 pre[x] = pre[y]; 78 pre[y] = x; 79 ch[x][!t] = y; 80 if(rt[y]) rt[y] = false, rt[x] = true; 81 else ch[pre[x]][ch[pre[x]][1] == y] = x; 82 update_max(y); 83 } 84 85 void P(int r) { 86 if(!rt[r]) P(pre[r]); 87 pushdown(r); 88 } 89 90 inline void Splay(int r) { 91 P(r); 92 while(!rt[r]) { 93 int f = pre[r], ff = pre[f]; 94 if(rt[f]) rotate(r); 95 else if((ch[ff][1] == f) == (ch[f][1] == r)) rotate(f), rotate(r); 96 else rotate(r), rotate(r); 97 } 98 update_max(r); 99 } 100 101 inline int access(int x) { 102 int y = 0; 103 while(x) { 104 Splay(x); 105 rt[ch[x][1]] = true, rt[ch[x][1] = y] = false; 106 update_max(x); 107 x = pre[y = x]; 108 } 109 return y; 110 } 111 112 inline void be_root(int r) { 113 access(r); 114 Splay(r); 115 update_rev(r); 116 } 117 118 inline void lca(int &u, int &v) { 119 access(v), v = 0; 120 while(u) { 121 Splay(u); 122 if(!pre[u]) return ; 123 rt[ch[u][1]] = true; 124 rt[ch[u][1] = v] = false; 125 update_max(u); 126 u = pre[v = u]; 127 } 128 } 129 130 inline int root(int u) { 131 while(pre[u]) u = pre[u]; 132 return u; 133 } 134 135 inline void link(int u, int v) { 136 if(u == v || root(u) == root(v)) puts("-1"); 137 else { 138 be_root(u); 139 pre[u] = v; 140 } 141 } 142 143 inline void cut(int u, int v) { 144 if(u == v || root(u) != root(v)) puts("-1"); 145 else { 146 be_root(u); 147 Splay(v); 148 pre[ch[v][0]] = pre[v]; 149 pre[v] = 0; 150 rt[ch[v][0]] = true; 151 ch[v][0] = 0; 152 update_max(v); 153 } 154 } 155 156 inline void modity(int u, int v, int w) { 157 if(root(u) != root(v)) puts("-1"); 158 else { 159 lca(u, v); 160 update_add(ch[u][1], w); 161 update_add(v, w); 162 key[u] += w; 163 update_max(u); 164 } 165 } 166 167 inline void query(int u, int v) { 168 if(root(u) != root(v)) puts("-1"); 169 else { 170 lca(u, v); 171 printf("%d ", max(max(maxt[v], maxt[ch[u][1]]), key[u])); 172 } 173 } 174 175 int main() { 176 while(scanf("%d", &n) != EOF) { 177 init(); 178 for(int i = 1; i < n; ++i) { 179 int u, v; 180 scanf("%d%d", &u, &v); 181 add_edge(u, v); 182 } 183 for(int i = 1; i <= n; ++i) scanf("%d", &key[i]); 184 pre[1] = -1; dfs(1); pre[1] = 0; 185 scanf("%d", &m); 186 while(m--) { 187 scanf("%d", &op); 188 if(op == 1) { 189 int x, y; 190 scanf("%d%d", &x, &y); 191 link(x, y); 192 } 193 if(op == 2) { 194 int x, y; 195 scanf("%d%d", &x, &y); 196 cut(x, y); 197 } 198 if(op == 3) { 199 int x, y, w; 200 scanf("%d%d%d", &w, &x, &y); 201 modity(x, y, w); 202 } 203 if(op == 4) { 204 int x, y; 205 scanf("%d%d", &x, &y); 206 query(x, y); 207 } 208 } 209 puts(""); 210 } 211 }