#define REP(a,b) for(int a=0; a<(b); ++a)
#define REP2(a,b) for(int a=1; a<=(b); ++a)
#define FWD(a,b,c) for(int a=(b); a<(c); ++a)
#define BCK(a,b,c) for(int a=(b)-1; a>=(c); --a)
#define BCK2(a,b,c) for(int a=(b); a>(c); --a)
#define FWDS(a,b,c,d) for(int a=(b); a<(c); a+=d)
#define ALL(a) (a).begin(), (a).end()
#define SIZE(a) ((int)(a).size())
#define VAR(x) #x ": " << x << " "
#define FILL(x,y) memset(x,y,sizeof(x))
#define MIN(a,b) (((a)<(b))?(a):(b))
#define MAX(a,b) (((a)>(b))?(a):(b))
#define FAST ios_base::sync_with_stdio(0);cin.tie(0);
#define x first
#define y second
#define st first
#define nd second
#define mp make_pair
#define pb push_back
#define l(n) (n<<1)
#define r(n) ((n<<1)+1)
#define f(n) (n>>1)
#define lsb(a) (a&-a)
#include<vector>
#include<stack>
#include<queue>
#include<algorithm>
using namespace std;
#ifndef ONLINE_JUDGE
#include<fstream>
ifstream cin("heavypath.in");
ofstream cout("heavypath.out");
#else
#include<iostream>
#endif
const int NMAX = 100005;
const int INF = 1 << 31;
const int dx[] = {0, 0, -1, 1}; //1,1,-1,1};
const int dy[] = {-1, 1, 0, 0}; //1,-1,1,-1};
typedef long long LL;
typedef pair<int, int> PII;
typedef long double K;
typedef pair<K, K> PKK;
typedef vector<int> VI;
int n;
VI G[NMAX];
int viz[NMAX], w[NMAX], lvl[NMAX];
int val[NMAX];
int k; // path number (max = logN)
VI P[NMAX];
int path[NMAX], size[NMAX], conn[NMAX], pos[NMAX];
int A[NMAX>>2];
void _update(int n, int l, int r, int poz, int val, int phi)
{
if(l==r)
{
A[n + phi]=val;
return;
}
int pivot=(l+r)>>1;
if(poz <= pivot)
_update(l(n), l, pivot, poz, val, phi);
else
_update(r(n), pivot+1, r, poz, val, phi);
A[n + phi] = max(A[l(n) + phi], A[r(n) + phi]);
}
int _query(int n, int l, int r, int x, int y, int phi)
{
if(x<=l && r<=y)
return A[n + phi];
int pivot = (l+r)>>1, rs=0;
if(x <= pivot)
rs=_query(l(n), l, pivot, x, y, phi);
if(pivot < y)
rs=max(rs, _query(r(n), pivot+1, r, x, y, phi));
return rs;
}
void dfs(int n)
{
viz[n]=1;
w[n]=1;
int son=0;
bool end=true;
REP(i,G[n].size())
{
int curr=G[n][i];
if(!viz[curr])
{
end=false;
lvl[curr]=lvl[n]+1;
dfs(curr);
w[n]+=w[curr];
if(!son)
son=curr;
else if(w[son] < w[curr])
son=curr;
}
}
if(end)
{
path[n]=++k;
P[path[n]].pb(n);
size[path[n]]=1;
return;
}
P[path[son]].pb(n);
size[path[son]]++;
path[n]=path[son];
REP(i,G[n].size())
{
int curr=G[n][i];
if(curr != son && lvl[curr] > lvl[n])
{
conn[path[curr]]=n;
}
}
}
int a,b,m;
int t;
int main() {
FAST;
cin>>n;
REP(i,n-1){
cin>>a>>b;
G[a].pb(b);
G[b].pb(a);
}
lvl[1]=1;
dfs(1);
REP2(i,k)
{
reverse(P[i].begin(), P[i].end());
if(i>1)
pos[i] = pos[i-1] + 4*size[i-1];
}
cin>>m;
REP(i,m)
{
cin>>t>>a>>b;
if(t==0)
{
_update(1, 1, size[path[a]], lvl[a] - lvl[conn[path[a]]], b, pos[path[a]]);
}
else
{
int rs=0;
while(1)
{
if(path[a] == path[b])
{
if(lvl[a] > lvl[b])
swap(a,b);
rs=max(rs, _query(1, 1, size[path[a]], lvl[a] - lvl[conn[path[a]]], lvl[b] - lvl[conn[path[b]]], pos[path[a]]));
break;
}
if(lvl[conn[path[a]]] < lvl[conn[path[b]]])
swap(a,b);
rs=max(rs, _query(1, 1, size[path[a]], 1, lvl[a] - lvl[conn[path[a]]], pos[path[a]]));
a=conn[path[a]];
}
cout<<rs<<"\n";
}
}
return 0;
}