#pragma comment(linker, "/STACK:102400000,102400000")
#include <iostream>
#include <cstdio>
#include <cstring>
#include <cmath>
#include <algorithm>
#include <queue>
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1
using namespace std;
typedef long long ll;
const int N = 200010;
const int inf = 0x3f3f3f3f;
struct edge
{
    int to,next;
    edge(){}
    edge(int to,int next):to(to),next(next){}
}e[N<<1];
int head[N],tot;
int top[N],a[N],b[N];
int fa[N],dep[N],num[N],p[N],fp[N],son[N],pos;
void init()
{
    memset(head,-1,sizeof head);
    tot=0;pos=0;
    memset(son,0,sizeof son);
}
void addedge(int u,int v)
{
    e[tot]=edge(v,head[u]);
    head[u]=tot++;
}
//void dfs1(int u,int pre,int d)
//{
//    dep[u]=d;
//    fa[u]=pre;num[u]=1;
//    for(int i=head[u];~i;i=e[i].next)
//    {
//        int v=e[i].to;
//        if(v==pre)continue;
//        dfs1(v,u,d+1);
//        num[u]+=num[v];
//        if(son[u]==0||num[v]>num[son[u]])son[u]=v;
//    }
//}
//void getpos(int u,int sp)
//{
//    top[u]=sp;
//    p[u]=++pos;
//    fp[p[u]]=u;
//    if(son[u]==0)return;
//    getpos(son[u],sp);
//    for(int i=head[u];~i;i=e[i].next)
//    {
//        int v=e[i].to;
//        if(v!=son[u]&&v!=fa[u])
//        getpos(v,v);
//    }
//}


struct node
{
    int lsum,rsum,msum,sum;
    void sp()
    {
        swap(lsum,rsum);
    }
}s[N<<2];
int col[N<<2];
node calc(node a,node b)
{
    node c;
    c.sum=a.sum+b.sum;
    c.msum=max(a.msum,b.msum);
    c.lsum=max(a.lsum,a.sum+b.sum);
    c.rsum=max(b.rsum,a.sum+b.sum);
    c.lsum=max(c.lsum,a.sum+b.lsum);
    c.rsum=max(c.rsum,b.sum+a.rsum);
    c.msum=max(c.msum,max(c.lsum,c.rsum));
    c.msum=max(c.msum,a.rsum+b.lsum);
    return c;
}
void pushup(int rt)
{
    s[rt]=calc(s[rt<<1],s[rt<<1|1]);
}
void build(int l,int r,int rt)
{
    col[rt]=inf;
    if(l==r)
    {
        s[rt].lsum=s[rt].rsum=s[rt].msum=s[rt].sum=b[l];
        return;
    }
    int m=(l+r)>>1;
    build(lson);
    build(rson);
    pushup(rt);
}
void pushdown(int rt,int len)
{
    if(col[rt]!=inf)
    {
        col[rt<<1]=col[rt<<1|1]=col[rt];
        s[rt<<1].sum=col[rt]*(len-(len>>1));
        s[rt<<1|1].sum=col[rt]*(len>>1);
        if(col[rt]>0)
        {
            s[rt<<1].lsum=s[rt<<1].rsum=s[rt<<1].msum=col[rt]*(len-(len>>1));
            s[rt<<1|1].lsum=s[rt<<1|1].rsum=s[rt<<1|1].msum=col[rt]*(len>>1);
        }
        else
        {
            s[rt<<1].lsum=s[rt<<1].rsum=s[rt<<1].msum=col[rt];
            s[rt<<1|1].lsum=s[rt<<1|1].rsum=s[rt<<1|1].msum=col[rt];
        }
        col[rt]=inf;
    }
}
void update(int L,int R,int c,int l,int r,int rt)
{
    if(L==l&&r==R)
    {
        col[rt]=c;
        s[rt].sum=col[rt]*(r-l+1);
        if(col[rt]>0)
        {
            s[rt].lsum=s[rt].rsum=s[rt].msum=col[rt]*(r-l+1);
        }
        else
        {
            s[rt].lsum=s[rt].rsum=s[rt].msum=col[rt];
        }
        return;
    }
    pushdown(rt,r-l+1);
    int m=(l+r)>>1;
    if(R<=m)update(L,R,c,lson);
    else if(L>m)update(L,R,c,rson);
    else
    {
       update(L,m,c,lson);
       update(m+1,R,c,rson);
    }
    pushup(rt);
}
void change(int u,int v,int c)
{
    int f1=top[u],f2=top[v];
    while(f1!=f2)
    {
        if(dep[f1]<dep[f2])
        {
            swap(f1,f2);
            swap(u,v);
        }
        update(p[f1],p[u],c,1,pos,1);
        u=fa[f1];f1=top[u];
    }
    if(dep[u]>dep[v])swap(u,v);
    update(p[u],p[v],c,1,pos,1);
}
node query(int L,int R,int l,int r,int rt)
{
    if(L==l&&r==R)return s[rt];
    pushdown(rt,r-l+1);
    int m=(l+r)>>1;
    if(R<=m)return query(L,R,lson);
    else if(L>m)return query(L,R,rson);
    else
    {
        node a=query(L,m,lson);
        node b=query(m+1,R,rson);
        return calc(a,b);
    }
}
node lca(int u,int v)
{
    int f1=top[u],f2=top[v],first1=1,first2=1;
    node tmp1,tmp2,tmp;
    while(f1!=f2)
    {
        if(dep[f1]<dep[f2])
        {
            if(first2)
            {
                tmp2=query(p[f2],p[v],1,pos,1);
                first2=0;
            }
            else
            {
                tmp2=calc(query(p[f2],p[v],1,pos,1),tmp2);
            }
            v=fa[f2];f2=top[v];
        }
        else
        {
            if(first1)
            {
                tmp1=query(p[f1],p[u],1,pos,1);
                tmp1.sp();
                first1=0;
            }
            else
            {
                tmp=query(p[f1],p[u],1,pos,1);
                tmp.sp();
                tmp1=calc(tmp1,tmp);
            }
            u=fa[f1];f1=top[u];
        }
    }

    if(dep[u]>dep[v])
    {
        if(first1)
        {
            tmp1=query(p[v],p[u],1,pos,1);
            tmp1.sp();
            first1=0;
        }
        else
        {
            tmp=query(p[v],p[u],1,pos,1);
            tmp.sp();
            tmp1=calc(tmp1,tmp);
        }
    }
    else
    {
        if(first2)
        {
            tmp2=query(p[u],p[v],1,pos,1);
            first2=0;
        }
        else tmp2=calc(query(p[u],p[v],1,pos,1),tmp2);
    }
    if(first1&&!first2)
    {
        return tmp2;
    }
    else if(!first1&&first2)return tmp1;
    else
    {
        return calc(tmp1,tmp2);
    }
}
int que[N*2],iii[N];

vector<int>G[N];
void buildlist(int n)
{
    int ft = 0, rear = 0;
    que[rear++] = 1;
    fa[1] = 0;
    dep[1] = 1;
    while(ft < rear)
    {
        int u = que[ft++];
        for(int i = 0; i < G[u].size(); i++)
        {
            int v = G[u][i];
            if(v == fa[u]) continue;
            fa[v] = u;
            que[rear++] = v;
            dep[v] = dep[u]+1;
        }
    }
    memset(num, 0, sizeof (num));
    for(int i = n-1; i >= 0; i--)
    {
        int u = que[i];
        num[u]++;
        num[fa[u]] += num[u];
    }
    for(int i = 1; i <= n; i++)
    {
        for(int j = 1; j < G[i].size(); j++) if(G[i][j] != fa[i])
                if(G[i][0] == fa[i] || num[G[i][j]] > num[G[i][0]])
                    swap(G[i][0], G[i][j]);
    }
    top[1] = 1;
    for(int i = 1; i < n; i++)
    {
        int u = que[i];
        if(G[fa[u]][0] == u) top[u] = top[fa[u]];
        else top[u] = u;
    }
    memset(iii, 0, sizeof (iii));
    ft = 0;
    que[++ft] = 1;
    p[1] = ++pos;
    b[1] = a[1];
    while(ft)
    {
        int u = que[ft];
        if(iii[u] >= G[u].size()) ft--;
        else if(G[u][iii[u]] == fa[u]) iii[u]++;
        else
        {
            int v = G[u][iii[u]];
            que[++ft] = v;
            p[v] = ++pos;
            b[p[v]] = a[v];
            iii[u]++;
        }
    }
  //  for(int i = 1 ; i <= n ; ++ i) updata(i , i , b[i] , 1, pos, 1);
}
int main()
{
    int n,q;
    while(scanf("%d%d",&n,&q)>0)
    {
        for(int i=1;i<=n;i++)scanf("%d",&a[i]),G[i].clear();
        init();
        for(int i=1;i<n;i++)
        {
            int u,v;
            scanf("%d%d",&u,&v);
            addedge(u,v);
            addedge(v,u);
            G[u].push_back(v);G[v].push_back(u);
        }
     //   dfs1(1,0,0);
      //  getpos(1,1);
        buildlist(n);
        build(1,pos,1);
        while(q--)
        {
            int op,a,b,c;
            scanf("%d%d%d%d",&op,&a,&b,&c);
            if(op==1)
            {
                change(a,b,c);
            }
            else
            {
                node temp=lca(a,b);
                printf("%d\n",temp.msum);
            }
        }
    }
    return 0;
}

Measured memory_bytes: 37592