// include //------------------------------------------ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include using namespace std; const long long INF = 4e18; const long long NINF = 1 - INF; int N; vector a; // [u] := 頂点 u の価値 vector > G; // 隣接リスト int main() { int Q; cin >> N >> Q; G.resize(N); a.resize(N); for (long long &x : a) cin >> x; for (int i = 0; i < N - 1; i++) { int u, v; cin >> u >> v; u--; v--; G[u].push_back(v); G[v].push_back(u); } int query_times = 0; // カウンター(何回目のbfsの結果かを担当する) vector > visited(N + 1, make_pair(-1, -1)); // second は前の頂点 vector on_catapilar_path(N + 1, -1); // [x]:= query_times なら、頂点 x がそのクエリでの毛虫パス上に含まれる while (Q-- > 0) { long long t, u, v; cin >> t >> u >> v; query_times++; if (t == 0) { u--; a[u] += v; } else { u--; v--; queue q; q.push(u); visited[u] = {query_times, -1}; while (!q.empty()) { int now = q.front(); q.pop(); for (int nx : G[now]) { if (visited[nx].first == query_times) continue; q.push(nx); visited[nx] = {query_times, now}; } } int now = v; while (true) { on_catapilar_path[now] = query_times; for (int nx : G[now]) on_catapilar_path[nx] = query_times; if (now == u) break; now = visited[now].second; } long long res = 0; for (int x = 0; x <= N; x++) if (on_catapilar_path[x] == query_times) res += a[x]; cout << res << endl; } } return 0; }