// 当初のwriter解 #include #include #include #include #include using namespace std; template class SparseTable{ vector> table; //[i][x] := 左端が i の、連続する 2^x 個の区間の merge T merge(T a , T b){ if(a < b)return a; else return b; } int N; vector A; public: SparseTable(){} SparseTable(vectora_){ A = a_; N = A.size(); int k = 0; int s = 1; while(s < N){ s *= 2; k += 1; } table.resize(N , vector(k+1)); for(int i = 0 ; i < N ; i++)table[i][0] = A[i]; for(int x = 1 ; x <= k ; x++){ for(int i = 0 ; i < N ; i++){ int mid = i + (1<<(x-1)); if(mid >= N)table[i][x] = table[i][x-1]; else table[i][x] = merge(table[i][x-1] , table[mid][x-1]); } } } // [l,r) T query(int l , int r){ assert(l < r); int range = r-l; int wid = 1; int k = 0; while(wid <= range){ k++; wid *= 2; } wid/=2; k--; int l2 = r-wid; if(l2 >= N)return table[l][k]; return merge(table[l][k] , table[l2][k]); } }; class EulerTour{ vector >G;// 使い捨て public : vector tour;// ET vector Left;// [x] := tour において x が初めて登場する index EulerTour(){} EulerTour(vector > G_ , int root = 1):G(G_){ stack S;// (now , parent) S.emplace(root); Left.resize(G.size()); vector parent(G.size() , -1); while(!S.empty()){ int now = S.top(); S.pop(); if(now == -1)break; tour.push_back(now); if(G[now].size() != 0 && G[now].back() == parent[now])G[now].pop_back(); if(G[now].size() == 0)S.push(parent[now]); else{ parent[G[now].back()] = now; S.push(G[now].back()); G[now].pop_back(); } } for(int i = int(tour.size()) - 1 ; i >= 0 ;i--){ Left[tour[i]] = i; } } }; int N; int root = 1; vector a; // [u] := 頂点 u の価値 vector a_adj; // [u] := 頂点 u に隣接する頂点の価値の和(自身を除く) vector > G; // 隣接リスト vector depth; // [u] := 頂点 u の深さ vector sum; // [u] := root から u までパス上の各頂点に対して価値の総和 vector sum_adj; // [u] := root から u までパス上の各頂点に対して、「その頂点に隣接する頂点の価値の和(自身を除く)」の 総和 void reconstruct(); EulerTour E; SparseTable> S; void init(){ reconstruct(); vector> A; E = EulerTour(G,root); for(int i = 0 ; i s; s.push(root); vector memo(N + 1, false); sum[root] = a[root]; sum_adj[root] = a_adj[root]; depth[root] = 0; // dfs で色々と計算する while (!s.empty()) { int now = s.top(); s.pop(); memo[now] = true; for (int nx : G[now]) { if (memo[nx]) continue; s.push(nx); sum[nx] = sum[now] + a[nx]; sum_adj[nx] = sum_adj[now] + a_adj[nx]; depth[nx] = depth[now] + 1; } } } int main() { int Q; cin >> N >> Q; G.resize(N + 1); a.resize(N + 1, 0); a_adj.resize(N + 1, 0); sum.resize(N + 1, 0); sum_adj.resize(N + 1, 0); depth.resize(N + 1, 0); for (int i = 0; i < N; i++) cin >> a[i + 1]; for (int i = 0; i < N - 1; i++) { int u, v; cin >> u >> v; G[u].push_back(v); G[v].push_back(u); } for (int u = 1; u < N + 1; u++) { for (int nx : G[u]) a_adj[nx] += a[u]; } init(); int border = sqrt(N); vector > query_stack; for (int c = 1; c <= Q; c++) { if (c % border == 0) { while (int(query_stack.size()) > 0) { int x = query_stack.back().first; long long v = query_stack.back().second; query_stack.pop_back(); a[x] += v; } for (int i = 0; i < N + 1; i++) a_adj[i] = 0; for (int u = 1; u < N + 1; u++) { for (int nx : G[u]) a_adj[nx] += a[u]; } reconstruct(); } int t, u, v; cin >> t >> u >> v; if (t == 0) { query_stack.emplace_back(u, (long long)v); } else { long long res = query(u, v); for (pair data : query_stack) { if (is_adjacent(u, v, data.first)) { res += data.second; } } cout << res << endl; } } return 0; }