#include<bits/stdc++.h>
using namespace std;

#define int long long
typedef vector<int>vint;
typedef pair<int,int>pint;
typedef vector<pint>vpint;
#define rep(i,n) for(int i=0;i<(n);i++)
#define reps(i,f,n) for(int i=(f);i<(n);i++)
#define all(v) (v).begin(),(v).end()
#define each(it,v) for(__typeof((v).begin()) it=(v).begin();it!=(v).end();it++)
#define pb push_back
#define fi first
#define se second
template<typename A,typename B>inline void chmin(A &a,B b){if(a>b)a=b;}
template<typename A,typename B>inline void chmax(A &a,B b){if(a<b)a=b;}

const int INF=1001001001001001001ll;

struct node{
    int v,l,r,s;
    node(int a){
        v=l=r=s=a;
    }
    node(int v,int l,int r,int s):v(v),l(l),r(r),s(s){}
    node(){
        v=l=r=-INF;
        s=0;
    }
};
node operator+(const node &a,const node &b){
    node c;
    c.v=max(max(a.v,b.v),a.r+b.l);
    c.s=a.s+b.s;
    c.l=max(a.l,a.s+b.l);
    c.r=max(b.r,b.s+a.r);
    return c;
}

struct segtree{
    static const int SEG=1<<18;
    vint put;
    vector<node>dat;
    segtree():put(SEG*2,INF),dat(SEG*2){}

    inline void push(int k,int l,int r){
        if(put[k]==INF)return;
        if(put[k]>=0)dat[k]=node(put[k]*(r-l));
        else dat[k]=node(put[k],put[k],put[k],put[k]*(r-l));

        if(k<SEG-1){
            put[k*2+1]=put[k];
            put[k*2+2]=put[k];
        }
        put[k]=INF;
    }

    void update(int a,int b,int x,int k=0,int l=0,int r=SEG){
        push(k,l,r);
        if(r<=a||b<=l)return;
        if(a<=l&&r<=b){
            put[k]=x;
            push(k,l,r);
            return;
        }
        update(a,b,x,k*2+1,l,(l+r)/2);
        update(a,b,x,k*2+2,(l+r)/2,r);
        dat[k]=dat[k*2+1]+dat[k*2+2];
    }
    node query(int a,int b,int k=0,int l=0,int r=SEG){
        push(k,l,r);
        if(r<=a||b<=l)return node();
        if(a<=l&&r<=b)return dat[k];
        return query(a,b,k*2+1,l,(l+r)/2)+query(a,b,k*2+2,(l+r)/2,r);
    }
};

const int SIZE=222222;

int N,Q;
int W[SIZE];
vint G[SIZE];

int par[SIZE],dep[SIZE],hev[SIZE],pos[SIZE],head[SIZE],sz[SIZE];
segtree seg;

void dfs(){
    vint vs={0};
    par[0]=-1;
    dep[0]=0;
    rep(i,N){
        int v=vs[i];
        for(auto u:G[v]){
            if(u==par[v])continue;
            par[u]=v;
            dep[u]=dep[v]+1;
            vs.pb(u);
        }
    }

    for(int i=vs.size()-1;i>=0;i--){
        int v=vs[i];
        sz[v]=1;
        hev[v]=-1;
        int ma=0;
        for(auto u:G[v]){
            if(u==par[v])continue;
            if(ma<sz[u]){
                ma=sz[u];
                hev[v]=u;
            }
            sz[v]+=sz[u];
        }
    }
    /*
    par[v]=p;
    dep[v]=d;
    hev[v]=-1;
    int ma=0,sum=1;
    rep(i,G[v].size()){
        int to=G[v][i];
        if(to==p)continue;
        int tmp=dfs(to,v,d+1);
        if(ma<tmp){
            ma=tmp;
            hev[v]=to;
        }
        sum+=tmp;
    }
    return sum;
    */
}


void init(){
    dfs();
    int idx=0;
    rep(i,N){
        if(~par[i]&&hev[par[i]]==i)continue;
        for(int j=i;~j;j=hev[j]){
            head[j]=i;
            pos[j]=idx++;
        }
    }
    rep(i,N){
        seg.update(pos[i],pos[i]+1,W[i]);
    }
}

void query1(int a,int b,int c){
    while(head[a]!=head[b]){
        if(dep[head[a]]<dep[head[b]])swap(a,b);
        seg.update(pos[head[a]],pos[a]+1,c);
        a=par[head[a]];
    }
    if(dep[a]>dep[b])swap(a,b);
    seg.update(pos[a],pos[b]+1,c);
}

int query2(int a,int b){
    node x,y;
    while(head[a]!=head[b]){
        if(dep[head[a]]>=dep[head[b]]){
            x=seg.query(pos[head[a]],pos[a]+1)+x;
            a=par[head[a]];
        }
        else{
            y=seg.query(pos[head[b]],pos[b]+1)+y;
            b=par[head[b]];
        }
    }

    if(dep[a]>=dep[b]){
        x=seg.query(pos[b],pos[a]+1)+x;
    }
    else{
        y=seg.query(pos[a],pos[b]+1)+y;
    }

    swap(x.l,x.r);
    x=x+y;
    return x.v;
}

signed main(){
    scanf("%lld%lld",&N,&Q);
    rep(i,N)scanf("%lld",&W[i]);

    rep(i,N-1){
        int a,b;
        scanf("%lld%lld",&a,&b);
        a--;b--;
        G[a].pb(b);G[b].pb(a);
    }
    init();

    while(Q--){
        int t,a,b,c;
        scanf("%lld%lld%lld%lld",&t,&a,&b,&c);
        a--;b--;
        if(t==1){
            query1(a,b,c);
        }
        else{
            printf("%lld\n",query2(a,b));
        }
    }
    return 0;
}

Measured memory_bytes: 47300