This documentation is automatically generated by online-judge-tools/verification-helper
// verification-helper: PROBLEM https://judge.yosupo.jp/problem/vertex_add_path_sum
#include<bits/stdc++.h>
using namespace std;
#define call_from_test
#include "../../tree/heavylightdecomposition.cpp"
#include "../../datastructure/binaryindexedtree.cpp"
#undef call_from_test
signed main(){
cin.tie(0);
ios::sync_with_stdio(0);
int n,q;
cin>>n>>q;
vector<int> as(n);
for(int i=0;i<n;i++) cin>>as[i];
HLD G(n);
for(int i=1;i<n;i++){
int u,v;
cin>>u>>v;
G.add_edge(u,v);
}
G.build();
using ll = long long;
BIT<ll> bit(n);
for(int i=0;i<n;i++)
bit.add(G.vid[i],as[i]);
for(int i=0;i<q;i++){
int t;
cin>>t;
if(t==0){
int p,x;
cin>>p>>x;
bit.add(G.vid[p],x);
}
if(t==1){
int u,v;
cin>>u>>v;
ll res=0;
auto f=[&](int l,int r){res+=bit.query(l,r);};
G.for_each(u,v,f);
cout<<res<<'\n';
}
}
return 0;
}
#line 1 "test/yosupo/vertex_add_path_sum.test.cpp"
// verification-helper: PROBLEM https://judge.yosupo.jp/problem/vertex_add_path_sum
#include<bits/stdc++.h>
using namespace std;
#define call_from_test
#line 1 "tree/heavylightdecomposition.cpp"
#line 3 "tree/heavylightdecomposition.cpp"
using namespace std;
#endif
//BEGIN CUT HERE
class HLD{
private:
void dfs_sz(int v) {
auto &es=G[v];
if(~par[v]) es.erase(find(es.begin(),es.end(),par[v]));
for(int &u:es){
par[u]=v;
dfs_sz(u);
sub[v]+=sub[u];
if(sub[u]>sub[es[0]]) swap(u,es[0]);
}
}
void dfs_hld(int v,int &pos) {
vid[v]=pos++;
inv[vid[v]]=v;
for(int u:G[v]){
if(u==par[v]) continue;
nxt[u]=(u==G[v][0]?nxt[v]:u);
dfs_hld(u,pos);
}
}
public:
vector< vector<int> > G;
// vid: vertex -> idx
// inv: idx -> vertex
vector<int> vid,nxt,sub,par,inv;
HLD(int n):G(n),vid(n,-1),nxt(n),sub(n,1),par(n,-1),inv(n){}
void add_edge(int u,int v) {
G[u].emplace_back(v);
G[v].emplace_back(u);
}
void build(int r=0) {
int pos=0;
dfs_sz(r);
nxt[r]=r;
dfs_hld(r,pos);
}
int lca(int u,int v){
while(1){
if(vid[u]>vid[v]) swap(u,v);
if(nxt[u]==nxt[v]) return u;
v=par[nxt[v]];
}
}
template<typename F>
void for_each(int u,int v,const F& f) {
while(1){
if(vid[u]>vid[v]) swap(u,v);
f(max(vid[nxt[v]],vid[u]),vid[v]+1);
if(nxt[u]!=nxt[v]) v=par[nxt[v]];
else break;
}
}
template<typename F>
void for_each_edge(int u,int v,const F& f) {
while(1){
if(vid[u]>vid[v]) swap(u,v);
if(nxt[u]!=nxt[v]){
f(vid[nxt[v]],vid[v]+1);
v=par[nxt[v]];
}else{
if(u!=v) f(vid[u]+1,vid[v]+1);
break;
}
}
}
};
//END CUT HERE
#ifndef call_from_test
signed main(){
return 0;
};
#endif
#line 1 "datastructure/binaryindexedtree.cpp"
#line 3 "datastructure/binaryindexedtree.cpp"
using namespace std;
#endif
//BEGIN CUT HERE
template<typename T>
class BIT{
private:
// \sum_{j < i} v[j]
T sum(int i){
T s(0);
for(int x=i;x>0;x-=(x&-x))
s+=bit[x];
return s;
}
public:
int n;
vector<T> bit;
BIT(int n_):n(n_+1),bit(n_+2,0){}
// v[i] += a
void add(int i,T a){
for(int x=++i;x<=n;x+=(x&-x))
bit[x]+=a;
}
// \sum_{l <= i < r} v[i]
T query(int l,int r){return sum(r)-sum(l);}
// min({x | sum(x) >= w})
int lower_bound(const T w){
if(w<=0) return 0;
T r=w;
int x=0,p=1;
while(p<n) p<<=1;
for(int k=p;k>0;k>>=1){
if(x+k<=n and bit[x+k]<r){
r-=bit[x+k];
x+=k;
}
}
x++;
assert(sum(x-1)<w and sum(x)>=w);
return x;
}
// min({x | sum(x) > w})
int upper_bound(T w){return lower_bound(w+1);}
};
//END CUT HERE
#ifndef call_from_test
signed main(){
return 0;
}
#endif
#line 9 "test/yosupo/vertex_add_path_sum.test.cpp"
#undef call_from_test
signed main(){
cin.tie(0);
ios::sync_with_stdio(0);
int n,q;
cin>>n>>q;
vector<int> as(n);
for(int i=0;i<n;i++) cin>>as[i];
HLD G(n);
for(int i=1;i<n;i++){
int u,v;
cin>>u>>v;
G.add_edge(u,v);
}
G.build();
using ll = long long;
BIT<ll> bit(n);
for(int i=0;i<n;i++)
bit.add(G.vid[i],as[i]);
for(int i=0;i<q;i++){
int t;
cin>>t;
if(t==0){
int p,x;
cin>>p>>x;
bit.add(G.vid[p],x);
}
if(t==1){
int u,v;
cin>>u>>v;
ll res=0;
auto f=[&](int l,int r){res+=bit.query(l,r);};
G.for_each(u,v,f);
cout<<res<<'\n';
}
}
return 0;
}