1 #include<cstdio> 2 #include<cstring> 3 #include<queue> 4 #include<iostream> 5 #include<algorithm> 6 #define MAXN 300010 7 #define MAXM 600010 8 #define CLEAR(a,b) memset(a,b,sizeof(a)) 9 using namespace std; 10 int first[MAXN], next[MAXM], v[MAXM], e; 11 bool vis[MAXN]; 12 struct LCT { 13 int bef[MAXN]; 14 bool flip[MAXN]; 15 int next[MAXN][2], pre[MAXN], key[MAXN], add[MAXN], maxi[MAXN]; 16 void Init() { 17 CLEAR(next, 0); 18 CLEAR(pre, 0); 19 flip[0] = flip[1] = false; 20 add[0] = add[1] = 0; 21 bef[0] = bef[1] = 0; 22 key[0] = maxi[0] = 0; 23 } 24 inline void PushUp(int x) { 25 maxi[x] = max(key[x], max(maxi[next[x][0]], maxi[next[x][1]])); 26 } 27 inline void Inc(int x, int val) { 28 if (x) { 29 add[x] += val; 30 key[x] += val; 31 maxi[x] += val; 32 } 33 } 34 inline void PushDown(int x) { 35 if (add[x]) { 36 Inc(next[x][0], add[x]); 37 Inc(next[x][1], add[x]); 38 add[x] = 0; 39 } 40 if (flip[x]) { 41 flip[next[x][0]] ^= true; 42 flip[next[x][1]] ^= true; 43 swap(next[x][0], next[x][1]); 44 flip[x] = false; 45 } 46 } 47 void Rotate(int x, int kind) { 48 int y, z; 49 y = pre[x]; 50 z = pre[y]; 51 PushDown(x); 52 next[y][!kind] = next[x][kind]; 53 pre[next[x][kind]] = y; 54 next[z][next[z][1] == y] = x; 55 pre[x] = z; 56 next[x][kind] = y; 57 pre[y] = x; 58 PushUp(y); 59 } 60 void Splay(int x) { 61 int rt; 62 for (rt = x; pre[rt]; rt = pre[rt]) 63 ; 64 if (rt != x) { 65 bef[x] = bef[rt]; 66 bef[rt] = 0; 67 while (pre[x]) { 68 PushDown(pre[x]); 69 if (next[pre[x]][0] == x) 70 Rotate(x, 1); 71 else 72 Rotate(x, 0); 73 } 74 PushUp(x); 75 } else 76 PushDown(x); 77 } 78 void Access(int x) { 79 int father; 80 for (father = 0; x; x = bef[x]) { 81 Splay(x); 82 bef[next[x][1]] = x; 83 pre[next[x][1]] = 0; 84 next[x][1] = father; 85 pre[father] = x; 86 bef[father] = 0; 87 father = x; 88 PushUp(x); 89 } 90 } 91 int GetRoot(int x) { 92 Access(x); 93 Splay(x); 94 while (next[x][0]) 95 x = next[x][0]; 96 return x; 97 } 98 void MakeRoot(int x) { 99 Access(x); 100 Splay(x); 101 flip[x] ^= true; 102 } 103 void Join(int x, int y) { 104 MakeRoot(x); 105 MakeRoot(y); 106 bef[x] = y; 107 } 108 void Cut(int x) { 109 Access(x); 110 Splay(x); 111 bef[next[x][0]] = bef[x]; 112 bef[x] = 0; 113 pre[next[x][0]] = 0; 114 next[x][0] = 0; 115 PushUp(x); 116 } 117 void Update(int x, int y, int val) { 118 Access(y); 119 for (y = 0; x; x = bef[x]) { 120 Splay(x); 121 if (!bef[x]) { 122 key[x] += val; 123 Inc(y, val); 124 Inc(next[x][1], val); 125 return; 126 } 127 bef[next[x][1]] = x; 128 pre[next[x][1]] = 0; 129 next[x][1] = y; 130 pre[y] = x; 131 bef[y] = 0; 132 y = x; 133 PushUp(x); 134 } 135 } 136 int Query(int x, int y) { 137 Access(y); 138 for (y = 0; x; x = bef[x]) { 139 Splay(x); 140 if (!bef[x]) 141 return max(key[x], max(maxi[next[x][1]], maxi[y])); 142 bef[next[x][1]] = x; 143 pre[next[x][1]] = 0; 144 next[x][1] = y; 145 pre[y] = x; 146 bef[y] = 0; 147 y = x; 148 PushUp(x); 149 } 150 return -1; 151 } 152 } lct; 153 int INT() { 154 int res; 155 char ch; 156 while (ch = getchar(), !isdigit(ch)) 157 ; 158 for (res = ch - '0'; ch = getchar(), isdigit(ch);) 159 res = res * 10 + ch - '0'; 160 return res; 161 } 162 inline void AddEdge(int x, int y) { 163 v[e] = y; 164 next[e] = first[x]; 165 first[x] = e++; 166 } 167 void BFS(int x) { 168 int i, y; 169 queue<int> q; 170 memset(vis, false, sizeof(vis)); 171 vis[x] = true; 172 q.push(x); 173 while (!q.empty()) { 174 x = q.front(); 175 q.pop(); 176 for (i = first[x]; i != -1; i = next[i]) { 177 y = v[i]; 178 if (!vis[y]) { 179 lct.bef[y] = x; 180 lct.add[y] = 0; 181 lct.flip[y] = false; 182 vis[y] = true; 183 q.push(y); 184 } 185 } 186 } 187 } 188 int main() { 189 int n, i, q; 190 int cmd, x, y, val; 191 while (~scanf("%d", &n)) { 192 lct.Init(); 193 memset(first, -1, sizeof(first)); 194 for (e = 0, i = 1; i < n; i++) { 195 x = INT(), y = INT(); 196 AddEdge(x, y); 197 AddEdge(y, x); 198 } 199 BFS(1); 200 for (i = 1; i <= n; i++) 201 lct.key[i] = INT(); 202 q = INT(); 203 while (q--) { 204 cmd = INT(); 205 if (cmd == 1) { 206 x = INT(), y = INT(); 207 if (lct.GetRoot(x) == lct.GetRoot(y)) 208 puts("-1"); 209 else 210 lct.Join(x, y); 211 } else if (cmd == 2) { 212 x = INT(), y = INT(); 213 if (x == y || lct.GetRoot(x) != lct.GetRoot(y)) 214 puts("-1"); 215 else { 216 lct.MakeRoot(x); 217 lct.Cut(y); 218 } 219 } else if (cmd == 3) { 220 val = INT(), x = INT(), y = INT(); 221 if (lct.GetRoot(x) != lct.GetRoot(y)) 222 puts("-1"); 223 else 224 lct.Update(x, y, val); 225 } else { 226 x = INT(), y = INT(); 227 if (lct.GetRoot(x) != lct.GetRoot(y)) 228 puts("-1"); 229 else 230 printf("%d\n", lct.Query(x, y)); 231 } 232 } 233 putchar('\n'); 234 } 235 return 0; 236 }