题目大意:给出一棵带点权树,有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\n", 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 }