Problem: Problem

Aizu Magic School is a school where people who can use magic gather. Aizu Magic School has classrooms numbered from 1 to N and a corridor connecting the classrooms. You can go through the classrooms and corridors as many times as you like. In addition, Aizu Magic School has only one route that allows you to move between any classroom u and v through 0 or more classrooms and a corridor once. A magic circle is set up in each classroom. This magic square increases or decreases the magical power of those who enter the classroom each time they enter the classroom. Please answer the following two questions to help the students move.

question 1
0 A B
I want you to output the remaining amount of magical power when you move from classroom A to B. Including increase / decrease in classrooms A and B. Also, the amount of magical power at the beginning of this question is 0 each time.

Question 2
1 A C
The amount of increase / decrease in the magical power of classroom A changes by C.

Constraints

The input satisfies the following conditions.

* 1 ≤ N ≤ 2000
* 1 ≤ Ai ≤ 2000
* 1 ≤ Bi ≤ 2000
* 1 ≤ aj, bj ≤ N
* 1 ≤ Q ≤ 1000000
* -10000 ≤ Ci ≤ 10000

Input


N
cost1
::
costN
a1 b1
::
aN-1 bN-1
Q
query1
::
queryQ


The number N of classrooms is given at the beginning of the input. The following N lines are given the amount of magical power that increases or decreases when entering each classroom. The value on the i-line corresponds to the information in the classroom on the i-th line. Corridor information is given to the following N-1 line. The corridor on the jth line represents connecting the ajth and bjth classrooms. Then the number of questions Q is given. The following Q line is given the question in the above format.

Output

Output the answer to one line for each question 1.

Example

Input

7
1
2
3
4
5
6
7
1 2
1 3
3 4
3 5
5 6
5 7
10
0 1 7
0 2 7
1 1 15
0 1 7
0 2 7
0 1 1
1 1 -15
0 1 7
0 2 7
0 1 1


Output

16
18
31
33
16
16
18
1

Solution (in CPP):

Solution:
#include <bits/stdc++.h>
using namespace std;
using ll = long long;
#define rep(i,n) for(int (i)=0;(i)<(int)(n);++(i))
#define all(x) (x).begin(),(x).end()
#define pb push_back
#define fi first
#define se second
#define dbg(x) cout<<#x" = "<<((x))<<endl
template<class T,class U> ostream& operator<<(ostream& o, const pair<T,U> &p){o<<"("<<p.fi<<","<<p.se<<")";return o;}
template<class T> ostream& operator<<(ostream& o, const vector<T> &v){o<<"[";for(T t:v){o<<t<<",";}o<<"]";return o;}

//ノードの個数
const int MAX_V = 2002;
//ダブリングに必要なサイズ(log(MAX_V))
const int MAX_LOG_V = 11;
//木の隣接リスト表現
vector<int> G[MAX_V];
//根のノード番号
int root = 0;

//親を2^k回辿って到達するノード(根を通り過ぎる場合,-1)
int parent[MAX_LOG_V][MAX_V];
//根からの深さ
int depth[MAX_V];

//現在vに注目、親はp、深さd
void lca_dfs(int v, int p, int d){
    parent[0][v]=p;
    depth[v]=d;
    rep(i,G[v].size()){
        if(G[v][i]!=p){ //親でなければ子
            lca_dfs(G[v][i], v, d+1);
        }
    }
}

//初期化
void lca_init(int V){
    //parent[0]とdepthの初期化
    lca_dfs(root, -1, 0);
    //parentの初期化
    for(int k=0; k+1<MAX_LOG_V; ++k){
        for(int v=0; v<V; ++v){
            if(parent[k][v] < 0) parent[k+1][v]=-1;
            else parent[k+1][v] = parent[k][parent[k][v]];
        }
    }
}

//uとvのLCAを求める
int lca(int u, int v){
    //uとvの深さが同じになるまで親を辿る
    if(depth[u] > depth[v]) swap(u,v);
    for(int k=0; k<MAX_LOG_V; ++k){
        if((depth[v]-depth[u])>>k & 1) v = parent[k][v];
    }
    if(u==v) return u;
    //二分探索でLCAを求める
    for(int k=MAX_LOG_V-1; k>=0; --k){
        if(parent[k][u] != parent[k][v]){
            u=parent[k][u];
            v=parent[k][v];
        }
    }
    return parent[0][u];
}

const int N = 2002;
int n;
int c[N];

// dist from root
int d[N];
void calc_dist(int v, int par){
    for(int e:G[v])if(e!=par){
        d[e] = d[v]+c[e];
        calc_dist(e,v);
    }
}

const int B = 10000;
const int SZ = 100;

int main(){
    scanf(" %d", &n);
    rep(i,n) scanf(" %d", &c[i]);

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

    lca_init(n);

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

    vector<pair<int,int>> upd;
    rep(i,B){
        for(const auto &p:upd) c[p.fi] += p.se;
        upd.clear();

        d[root] = c[root];
        calc_dist(root, -1);

        rep(j,SZ){
            if(i*SZ + j == q) return 0;

            int type,x,y;
            scanf(" %d %d %d", &type, &x, &y);
            if(type == 0){
                // move x -> y
                --x;
                --y;
                int l = lca(x,y);
                if(l == y) swap(x,y);

                int ans = d[x]+d[y]-c[l];
                int par_l = parent[0][l];
                if(par_l != -1) ans -= 2*d[par_l];

                for(const auto &p:upd){
                    int v = p.fi;
                    int val = p.se;

                    bool on_path = false;
                    int vx = lca(v,x), vy = lca(v,y);
                    if(l == x){
                        if(vy==v && vx==x) on_path = true;
                    }
                    else{
                        if(v==l) on_path = true;
                        else{
                            if(vx != vy){
                                if(vx==l && vy==v) on_path = true;
                                if(vx==v && vy==l) on_path = true;
                            }
                        }
                    }

                    if(on_path) ans += val;
                }

                printf("%d\n", ans);
            }
            else{
                // update c[x] <- y
                --x;
                upd.pb({x,y});
            }
        }
    }


    return 0;
}