require 'set'

class LazySegmentTree
  def initialize(arr, l = 0, r = arr.size - 1)
    @l, @r = l, r
    @lazy = nil
    if l == r
      @sum = @left_seq = @seq = @right_seq = arr[l]
    else
      c = (l + r) / 2
      @left_child = self.class.new(arr, l, c)
      @right_child = self.class.new(arr, c + 1, r)
      aggregate
    end
  end

  attr_reader :l, :r, :sum, :left_seq, :seq, :right_seq, :lazy

  def aggregate
    @sum = @left_child.sum + @right_child.sum
    @left_seq = [
      @left_child.left_seq,
      @left_child.sum + @right_child.left_seq
    ].max
    @right_seq = [
      @right_child.right_seq,
      @right_child.sum + @left_child.right_seq
    ].max
    @seq = [
      @left_child.seq,
      @right_child.seq,
      @left_child.right_seq + @right_child.left_seq
    ].max
  end

  def update(l, r, x)
    if @l == @r
      @sum = @left_seq = @seq = @right_seq = x
    elsif l == @l && r == @r
      @lazy = x
    else
      force
      if r <= @left_child.r
        @left_child.update(l, r, x)
      elsif @right_child.l <= l
        @right_child.update(l, r, x)
      else
        @left_child.update(l, @left_child.r, x)
        @right_child.update(@right_child.l, r, x)
      end
      @left_child.force
      @right_child.force
      aggregate
    end
  end

  def force
    return if !@lazy
    x = @lazy
    @lazy = nil

    @sum = x * (@r - @l + 1)
    if x >= 0
      @left_seq = @seq = @right_seq = x * (@r - @l + 1)
    else
      @left_seq = @seq = @right_seq = x
    end

    @left_child.update(@left_child.l, @left_child.r, x)
    @right_child.update(@right_child.l, @right_child.r, x)
  end

  def query(l, r)
    force
    if @l == @r || (l == @l && r == @r)
      return [@sum, @left_seq, @seq, @right_seq]
    elsif r <= @left_child.r
      return @left_child.query(l, r)
    elsif @right_child.l <= l
      return @right_child.query(l, r)
    else
      sum1, left_seq1, seq1, right_seq1 = @left_child.query(l, @left_child.r)
      sum2, left_seq2, seq2, right_seq2 = @right_child.query(@right_child.l, r)
      return [
        sum1 + sum2,
        [left_seq1, sum1 + left_seq2].max,
        [seq1, seq2, right_seq1 + left_seq2].max,
        [right_seq1 + sum2, right_seq2].max
      ]
    end
  end
end

n, q = gets.split.map(&:to_i)
weights = [nil]
weights += gets.split.map(&:to_i)

undirected = (0..n).map { [] }
(n - 1).times do
  u, v = gets.split.map(&:to_i)
  undirected[u] << v
  undirected[v] << u
end

# orientation
tree = Hash[(1..n).map {|i| [i, []] }]
parent = {}
queue = [1]
reached = Set[1]
until queue.empty?
  u = queue.shift
  undirected[u].each do |v|
    next if reached.include?(v)
    reached << v
    tree[u] << v
    parent[v] = u
    queue << v
  end
end
out_deg = Hash[(1..n).map {|i| [i, tree[i].size] }]

# p tree
# p parent
# p out_deg

# compute subtree size
subtree_size = Hash[(1..n).map {|i| [i, 1] }]
queue = (1..n).select {|i| out_deg[i] == 0 }
paths = []
until queue.empty?
  i = queue.shift
  tree[i].each do |j|
    subtree_size[i] += subtree_size[j]
  end
  j = parent[i]
  if j
    out_deg[j] -= 1
    queue << j if out_deg[j] == 0
  end
end

# p subtree_size

# Heavy-Light Decomposition & Lazy Segment Trees
queue = [1]
position = {}
ord = 0

segs = []
until queue.empty?
  i = queue.shift
  path = [i]
  loop do
    heavy = true
    tree[i].sort_by {|j| -subtree_size[j]}.each do |j|
      if heavy
        path << j
        i = j
        heavy = false
      else
        queue << j
      end
    end
    break if heavy
  end
  seg = LazySegmentTree.new(path.map {|i| weights[i] })
  (0..path.size-1).each do |i|
    position[path[i]] = [seg, i, ord, path]
  end
  segs << seg
  ord += 1
end

# process queries
q.times do
  type, u, v, c = gets.split.map(&:to_i)
  # p [u, v]
  
  if type == 1
    seg1, i, o1, path1 = position[u]
    seg2, j, o2, path2 = position[v]
    until o1 == o2
      if o1 > o2
        seg1.update(0, i, c)
        seg1, i, o1, path1 = position[u = parent[path1[0]]]
      else
        seg2.update(0, j, c)
        seg2, j, o2, path2 = position[v = parent[path2[0]]]
      end
    end
    if i <= j
      seg1.update(i, j, c)
    else
      seg2.update(j, i, c)
    end

  else
    seg1, i, o1, path1 = position[u]
    seg2, j, o2, path2 = position[v]
    sum1, l_seq1, seq1, r_seq1 = 0, -Float::INFINITY, -Float::INFINITY, -Float::INFINITY
    sum2, l_seq2, seq2, r_seq2 = 0, -Float::INFINITY, -Float::INFINITY, -Float::INFINITY
    until o1 == o2
      if o1 > o2
        sum0, l_seq0, seq0, r_seq0 = seg1.query(0, i)
        sum1, l_seq1, seq1, r_seq1 = [
          sum0 + sum1,
          [l_seq0, sum0 + l_seq1].max,
          [seq0, seq1, r_seq0 + l_seq1].max,
          [r_seq0 + sum1, r_seq1].max
        ]
        seg1, i, o1, path1 = position[u = parent[path1[0]]]
      else
        sum0, l_seq0, seq0, r_seq0 = seg2.query(0, j)
        sum2, l_seq2, seq2, r_seq2 = [
          sum0 + sum2,
          [l_seq0, sum0 + l_seq2].max,
          [seq0, seq2, r_seq0 + l_seq2].max,
          [r_seq0 + sum2, r_seq2].max
        ]
        seg2, j, o2, path2 = position[v = parent[path2[0]]]
      end
    end
    if i <= j
      sum0, l_seq0, seq0, r_seq0 = seg1.query(i, j)
      sum2, l_seq2, seq2, r_seq2 = [
        sum0 + sum2,
        [l_seq0, sum0 + l_seq2].max,
        [seq0, seq2, r_seq0 + l_seq2].max,
        [r_seq0 + sum2, r_seq2].max
      ]
    else
      sum0, l_seq0, seq0, r_seq0 = seg2.query(j, i)
      sum1, l_seq1, seq1, r_seq1 = [
        sum0 + sum1,
        [l_seq0, sum0 + l_seq1].max,
        [seq0, seq1, r_seq0 + l_seq1].max,
        [r_seq0 + sum1, r_seq1].max
      ]
    end
    puts [seq1, seq2, l_seq1 + l_seq2].max
  end
end


Measured memory_bytes: 172960