#include<bits/stdc++.h>
typedef long long int ll;
typedef unsigned long long int ull;
#define BIG_NUM 2000000000
#define HUGE_NUM 1000000000000000000
#define MOD 1000000007
#define EPS 0.000000001
using namespace std;




#define NUM 2005

int N = 1;
int num_node;
int root = 0,euler_index = 0;
int MAX_LOG_V = 13;
int LEFT[NUM],RIGHT[NUM];


int parent[13][NUM],depth[NUM];
vector<int> G[NUM];
ll W[NUM],sum_W[NUM];
ll uniformity[8*NUM],partial[8*NUM];


//★★開区間なので注意★★

void init(ll first_N){
	while(N < first_N)N *= 2;
}

void add(ll left,ll right,ll value,ll node_id,ll node_left,ll node_right){

	if(right <= node_left || left >= node_right)return;
	else if(left <= node_left && right >= node_right){
		uniformity[node_id] += value;
	}else{
		partial[node_id] += (min(right,node_right)-max(left,node_left))*value;
		add(left,right,value,2*node_id+1,node_left,(node_left+node_right)/2);
		add(left,right,value,2*node_id+2,(node_left+node_right)/2,node_right);
	}
}

ll getSum(ll left,ll right,ll node_id,ll node_left,ll node_right){
	if(right <= node_left || left >= node_right)return 0;
	else if(left <= node_left && right >= node_right){
		return (node_right-node_left)*uniformity[node_id]+partial[node_id];

	}else{
		ll sum = (min(right,node_right)-max(left,node_left))*uniformity[node_id];

		sum += getSum(left,right,2*node_id+1,node_left,(node_left+node_right)/2);
		sum += getSum(left,right,2*node_id+2,(node_left+node_right)/2,node_right);
		return sum;
	}
}


void dfs(int node_id,int parent_id,int DEPTH,ll total_W){

	parent[0][node_id] = parent_id;
	depth[node_id] = DEPTH;
	LEFT[node_id] = euler_index++;
	sum_W[node_id] = total_W+W[node_id];

	for(int i = 0; i < G[node_id].size(); i++){
		if(G[node_id][i] == parent_id)continue;
		dfs(G[node_id][i],node_id,DEPTH+1,sum_W[node_id]);
	}
	RIGHT[node_id] = euler_index++;
}

//初期化
void init_lca(){

	dfs(root,-1,0,0);

	for(int k = 0; k + 1 < MAX_LOG_V; k++){
		for(int node_id = 0; node_id < num_node; node_id++){
			if(parent[k][node_id] < 0)parent[k+1][node_id] = -1; //node_idの2^k上のノードがルートノードより上なら、2^(k+1)上も同様とする
			else{
				parent[k+1][node_id] = parent[k][parent[k][node_id]];
			}
		}
	}
}

int lca(int left,int right){

	if(depth[left] > depth[right])swap(left,right);
	for(int k = 0; k < MAX_LOG_V; k++){
		if((depth[right]-depth[left]) >> k & 1){
			right = parent[k][right];
		}
	}
	if(left == right)return left;

	for(int k = MAX_LOG_V-1; k >= 0; k--){
		if(parent[k][left] != parent[k][right]){
			left = parent[k][left];
			right = parent[k][right];
		}
	}
	return parent[0][left];
}

int main(){

	scanf("%d",&num_node);

	for(int i = 0; i < num_node; i++){

		scanf("%lld",&W[i]);
	}


	int from,to;

	for(int i = 0; i < num_node-1; i++){

		scanf("%d %d",&from,&to);
		from--;
		to--;

		G[from].push_back(to);
		G[to].push_back(from);
	}

	init_lca();

	int first_N = RIGHT[root]+1; //セグ木における最下層のノードは、最低RIGHT[0]+1個あれば良い(+1は0オリジンのため)

	init(first_N);

	for(ll i = 0; i <= 2*N-2; i++){
		uniformity[i] = 0;
		partial[i] = 0;
	}

	int num_query;
	scanf("%d",&num_query);

	int command;

	ll A,B,LCA;

	for(int loop = 0; loop < num_query; loop++){

		scanf("%d %lld %lld",&command,&A,&B);

		if(command == 0){

			A--;
			B--;
			LCA = lca(A,B);

			ll cost_A = sum_W[A] + getSum(LEFT[A],LEFT[A]+1,0,0,N);
			ll cost_B = sum_W[B] + getSum(LEFT[B],LEFT[B]+1,0,0,N);
			ll cost_LCA = sum_W[LCA] + getSum(LEFT[LCA],LEFT[LCA]+1,0,0,N);

			printf("%lld\n",cost_A+cost_B-2*cost_LCA+W[LCA]);

		}else{

			A--;
			add(LEFT[A],RIGHT[A]+1,B,0,0,N);
			W[A] += B;
		}
	}

	return 0;
}




Measured memory_bytes: 3704