#include <bits/stdc++.h>
typedef long long ll;
const int INF = 1e9;
const int MOD = 1e9+7;
const ll LINF = 1e18;
using namespace std;
 
#define dump(x)  cout << #x << " = " << (x) << endl;
#define YES(n) cout << ((n) ? "YES" : "NO"  ) << endl
#define Yes(n) cout << ((n) ? "Yes" : "No"  ) << endl
#define POSSIBLE(n) cout << ((n) ? "POSSIBLE" : "IMPOSSIBLE"  ) << endl
#define Possible(n) cout << ((n) ? "Possible" : "Impossible"  ) << endl
#define possible(n) cout << ((n) ? "possible" : "impossible"  ) << endl
 
#define SANKOU(n,a,b) cout << ((n) ? (#a) : (#b) ) << endl
 
#define FOR(i,a,b) for(ll i=(a);i<(b);++i)
#define REP(i,n) for(ll i=0;i<(n);++i)
#define REPR(i,n) for(ll i=n;i>=0;i--)
 
#define FOREACH(x,a) for(auto&& (x) : (a) )
 
#define WFA(d,v) REP(k,v)REP(i,v)REP(j,v)d[i][j]=min(d[i][j],d[i][k]+d[k][j])
 
#define SCOUT(x) cout<<(x)<<" "
#define ENDL cout<<endl
 
#define VECCIN(x) for(auto&youso_: (x) )cin>>youso_
#define VECIN2(x,y) REP(i,x.size())cin>>x[i]>>y[i]
#define VECCOUT(x) if(1){for(auto tt=x.begin();tt!=x.end();tt++){if(tt!=x.begin())cout<<" ";cout<<(*tt);}cout<<endl;}
 
#define ALL(obj) (obj).begin(),(obj).end()
 
#define EXIST(n,x) (find(ALL(n),x)!=n.end())
#define UNIQUE(obj) sort(ALL( obj )); obj.erase(unique(ALL(obj)),obj.end())
#define EN(x) if(1){cout<<#x<<endl;return 0;}
#define COUT(x) cout<<(x)<<endl
void CINT(){}
template <class Head,class... Tail>
void CINT(Head&& head,Tail&&... tail){
    cin>>head;
    CINT(move(tail)...);
}
#define CIN(...) int __VA_ARGS__;CINT(__VA_ARGS__)
#define LCIN(...) ll __VA_ARGS__;CINT(__VA_ARGS__)
#define SCIN(...) string __VA_ARGS__;CINT(__VA_ARGS__)
 
template <class T = ll>
T IN(){T x;cin>>x;return (x);}
 
template <class Head>
void VT(Head head){}
template <class Head,class Seco,class... Tail>
void VT(Head&& head,Seco&& seco,Tail&&... tail){
    seco.resize(head);
    VT(head,move(tail)...);
}
void VT2(){}
template <class Head,class... Tail>
void VT2(Head&& head,Tail&&... tail){
  VECCIN(head);
  VT2(move(tail)...);
}
 
template <class Head>
void VT3(Head&& head){}
template <class Head,class Seco,class... Tail>
void VT3(Head&& head,Seco&& seco,Tail&&... tail){
  seco[head]=IN();
  VT3(head,move(tail)...);
}
 
#define VC1(n,...) V __VA_ARGS__;VT(n,__VA_ARGS__);VT2(__VA_ARGS__); //aaabbbccc
#define VC2(n,...) V __VA_ARGS__;VT(n,__VA_ARGS__);REP(i,n)VT3(i,__VA_ARGS__); //abcabcabc
 
// #include <boost/multiprecision/cpp_int.hpp>
// using namespace boost::multiprecision; // cpp_int
 
#define P pair<ll,ll>
#define V vector<ll>
#define M map<ll,ll>
#define S set<ll>
 
#define pb(a) push_back(a)
#define mp make_pair
 
struct Element{
    ll l,r,m,s;
    Element(ll val = -1e15) : l(val), r(val), m(val), s(val){}
};
 
class LazySegmentTree{//遅延セグ木 初期値0で総和を出すやつ
  public:
  LazySegmentTree(ll n,V v);
  void addVal(ll st,ll en,ll val,ll k,ll l,ll r);
  Element calcVal(ll st,ll en,ll k,ll l,ll r);//半開区間 3,6なら3,4,5の総和
  void eval(ll k,ll l,ll r);
  vector<Element> elements;
  V lazy;
  ll pnum;
};
 
Element build(Element& a, Element& b){
    if(a.m == -1e15 || b.m == -1e15)
        return a.m == -1e15 ? b : a;
    Element x;
    x.l = max(a.l, a.s + b.l);
    x.r = max(b.r, a.r + b.s);
    x.m = max({a.m, b.m, a.r + b.l});
    x.s = a.s + b.s;
    return x;
}
 
Element& rev(Element& x){
    swap(x.l, x.r);
    return x;
}
 
LazySegmentTree::LazySegmentTree(ll n,V v){
  pnum=1;while(pnum<n)pnum*=2;
  elements=vector<Element>(pnum*2-1, Element());
  lazy=V(pnum*2-1, MOD);
 
  REP(i,n)
    elements[i+pnum-1] = Element(v[i]);
  REPR(i,pnum-2)
    elements[i]=build(elements[i*2+1],elements[i*2+2]);
}
 
void LazySegmentTree::addVal(ll st,ll en,ll val,ll k=0,ll l=0,ll r=-1){
  if(r<0)r=pnum;
  eval(k,l,r);
  if(en<=l || r<=st) return ;
  if(st<=l && r<=en){
    lazy[k] = val;
    eval(k,l,r);
  }else{
    addVal(st,en,val,2*k+1,l,(l+r)/2);
    addVal(st,en,val,2*k+2,(l+r)/2,r);
    elements[k]=build(elements[2*k+1],elements[2*k+2]);
  }
}
 
void LazySegmentTree::eval(ll k,ll l,ll r){
  if(lazy[k] == MOD)return ;
  elements[k].l = max(1LL*lazy[k],1LL * (r-l) * lazy[k]);
  elements[k].r = max(1LL*lazy[k],1LL * (r-l) * lazy[k]);
  elements[k].m = max(1LL*lazy[k],1LL * (r-l) * lazy[k]);
  elements[k].s = 1LL * (r-l) * lazy[k];
  if(r-l>1){
    lazy[2*k+1]=lazy[k];
    lazy[2*k+2]=lazy[k];
  }
  lazy[k]=MOD;
 
}
 
Element LazySegmentTree::calcVal(ll st,ll en,ll k=0,ll l=0,ll r=-1) {
  if(r<0)r=pnum;
  eval(k,l,r);
 
  if(en<=l || r<=st)return Element(-1e15);
  if(st<=l && r<=en)return elements[k];
  Element vl = calcVal(st,en,2*k+1,l,(l+r)/2);
  Element vr = calcVal(st,en,2*k+2,(l+r)/2,r);
  return build(vl, vr);
}
 
 
 
class HeavyLightDecomposition{
public:
    ll n;
    vector<V> g;
    V rev, in, out, nxt, rin, size, depth;
 
    HeavyLightDecomposition(vector<V>& inp) :
        n(inp.size()),
        g(n),
        rev(n, 0),
        in(n, 0),
        out(n, 0),
        nxt(n, 0),
        rin(n, 0),
        size(n, 0),
        depth(n, -1)
    {
 
        function<void(ll, ll)> dfs_ed = [&](ll pos, ll dep){
            depth[pos]=dep;
            for(auto ed : inp[pos])
                if(depth[ed] == -1){
                    g[pos].pb(ed);
                    rev[ed] = pos;
                    dfs_ed(ed, dep + 1);
                }
        };
        dfs_ed(0, 0);
 
        function<void(ll)> dfs_sz = [&](ll v){
            size[v] = 1;
            for(auto &u: g[v]){
                dfs_sz(u);
                size[v] += size[u];
                if(size[u] > size[g[v][0]])
                    swap(u, g[v][0]);
            }
        };
        dfs_sz(0);
 
        ll t = 0;
 
        function<void(ll)> dfs_hld = [&](ll v){
            in[v] = t++;
            rin[in[v]] = v;
            for(auto u: g[v]){
                nxt[u] = (u == g[v][0] ? nxt[v] : u);
                dfs_hld(u);
            }
            out[v] = t;
        };
        dfs_hld(0);
    }
 
    P subtree(ll x){
        return make_pair(in[x], out[x]);
    }
 
    V subtree_path(ll x){
        return V(next(rin.begin(), in[x]), next(rin.begin(), out[x]));
    }
 
    P subsegment(ll x){
        return make_pair(in[nxt[x]], in[x] + 1);
    }
 
    V subsegment_path(ll x){
        return V(next(rin.begin(), in[nxt[x]]), next(rin.begin(), in[x] + 1));
    }
 
    vector<P> root_path_query(ll x){
        vector<P> ret;
        ret.emplace_back(subsegment(x));
        while(ret.back().first)
            ret.emplace_back(subsegment(rev[rin[ret.back().first]]));
 
        return ret;
    }
 
    ll lca(ll x, ll y){
 
        ll sx = rin[subsegment(x).first];
        ll sy = rin[subsegment(y).first];
        while(sx != sy){
            if(depth[sx] > depth[sy])
                x = rev[sx];
            else
                y = rev[sy];
            sx = rin[subsegment(x).first];
            sy = rin[subsegment(y).first];
        }
 
        return depth[x] < depth[y] ? x : y;
    }
 
    pair<vector<P>,vector<P>> two_poll_path(ll x, ll y){
        ll z = lca(x, y);
        P z_par = subsegment(z);
 
        vector<P> ret_x;
        ret_x.emplace_back(subsegment(x));
        while(ret_x.back().first != z_par.first)
            ret_x.emplace_back(subsegment(rev[rin[ret_x.back().first]]));
        ret_x.back().first = in[z];
 
        vector<P> ret_y;
        ret_y.emplace_back(subsegment(y));
        while(ret_y.back().first != z_par.first)
            ret_y.emplace_back(subsegment(rev[rin[ret_y.back().first]]));
        ret_y.back().first = in[z] + 1;
        if(ret_y.back().first >= ret_y.back().second)
            ret_y.pop_back();
 
        /*
        COUT("\n----");
        FOREACH(xx,ret_x){
            SCOUT(xx.first);
            COUT(xx.second);
        }
        COUT("----");
        FOREACH(xx,ret_y){
            SCOUT(xx.first);
            COUT(xx.second);
        }
        COUT("----\n");
        */
 
        return mp(ret_x, ret_y);
    }
 
};
 
 
 
int main(){
    CIN(n,q);
    VC1(n, w);
    vector<V> ed(n);
    REP(i,n-1){
        CIN(a,b);
        ed[a-1].pb(b-1);
        ed[b-1].pb(a-1);
    }
    HeavyLightDecomposition hl(ed);
 
    V vv(n);
    REP(i,n)
        vv[hl.in[i]] = w[i];
 
    LazySegmentTree lazy(n, vv);
 
    REP(f,q){
        CIN(t,a,b,c);
        if(t == 1){
            pair<vector<P>,vector<P>> p = hl.two_poll_path(a-1, b-1);
            FOREACH(xx,p.first)
                lazy.addVal(xx.first, xx.second, c);
            FOREACH(xx,p.second)
                lazy.addVal(xx.first, xx.second, c);
        }else{
            pair<vector<P>,vector<P>> p = hl.two_poll_path(a-1, b-1);
            Element el;
            /*
            for(auto it = prev(p.first.end()); it >= p.first.begin(); --it){
                auto& xx = *it;
            */
            for(auto it = prev(p.first.end()); it >= p.first.begin(); --it){
                auto& xx = *it;
 
                Element e = lazy.calcVal(xx.first, xx.second);
                el = build(el, e);
            }
            rev(el);
            if(!p.second.empty())
            for(auto it = prev(p.second.end()); it >= p.second.begin(); --it){
                auto& xx = *it;
                Element e = lazy.calcVal(xx.first, xx.second);
                el = build(el, e);
            }
            COUT(el.m);
        }
    }
 
}



Measured memory_bytes: 79696