#include <bits/stdc++.h>
using namespace std;
#define SC scanf
#define PF printf
#define ull unsigned long long
#define ld long double
#define D double
#define F first
#define S second
#define pb push_back
#define sort_a(a) sort(a.begin(),a.end());
#define sort_d(a) sort(a.rbegin(),a.rend());
#define READ(f) freopen(f, "r", stdin)
#define WRITE(f) freopen(f, "w", stdout)
#define rev(s) reverse(s.begin(),s.end())
#define __Heart__ ios_base::sync_with_stdio(false); cin.tie(NULL);
#define ll long long
typedef pair<int,int> PII;
const int MX = 1e5 + 5;
const int szAlph = 26;
int n, q, arr[MX], discovery_time[MX], finishing_time[MX], Time = 0;
char a[MX];
vector<int> Edge[MX];
int charToIndex(char c) {
return c - 'a';
}
char indexToChar(int index) {
return 'a' + index;
}
void DFS(int id, int par) {
discovery_time[id] = ++Time;
arr[Time] = charToIndex(a[id]);
for (int child : Edge[id]) {
if (child == par) continue;
DFS(child, id);
}
finishing_time[id] = Time;
}
//void DFS(int id, int par) {
// stack<pair<int, int>> st;
// st.push({id, par});
// vector<bool> is_vis (n + 1, false);
//
// while (!st.empty()) {
// auto it = st.top();
//
// if (!is_vis[it.F]) {
// is_vis[it.F] = true;
// discovery_time[it.F] = ++Time;
// arr[Time] = charToIndex(a[it.F]);
// for (int child : Edge[it.F]) {
// if (child != it.S) {
// st.push({child, it.F});
// }
// }
// } else {
// finishing_time[it.F] = Time;
// st.pop();
// }
// }
//}
struct SegmentTreeNode {
int maxFreq;
int minValWithMaxFreq;
int freqCount[szAlph];
SegmentTreeNode() : maxFreq(0), minValWithMaxFreq(INT_MAX) {
fill(freqCount, freqCount + szAlph, 0);
}
void merge(const SegmentTreeNode& left, const SegmentTreeNode& right) {
maxFreq = 0;
minValWithMaxFreq = INT_MAX;
fill(freqCount, freqCount + szAlph, 0);
for (int i = 0; i < szAlph; ++i) {
freqCount[i] = left.freqCount[i] + right.freqCount[i];
if (freqCount[i] > maxFreq) {
maxFreq = freqCount[i];
minValWithMaxFreq = i;
} else if (freqCount[i] == maxFreq) {
minValWithMaxFreq = min(minValWithMaxFreq, i);
}
}
}
};
SegmentTreeNode tree[MX * 4];
void init(int node, int b, int e) {
if (b == e) {
tree[node].freqCount[arr[b]] = 1;
tree[node].maxFreq = 1;
tree[node].minValWithMaxFreq = arr[b];
return;
}
int mid = (b + e) / 2;
int left = node * 2;
int right = node * 2 + 1;
init(left, b, mid);
init(right, mid + 1, e);
tree[node].merge(tree[left], tree[right]);
}
SegmentTreeNode query(int node, int b, int e, int i, int j) {
if (i > e || j < b) {
return SegmentTreeNode();
}
if (b >= i && e <= j) {
return tree[node];
}
int mid = (b + e) / 2;
int left = node * 2;
int right = node * 2 + 1;
SegmentTreeNode leftResult = query(left, b, mid, i, j);
SegmentTreeNode rightResult = query(right, mid + 1, e, i, j);
SegmentTreeNode result;
result.merge(leftResult, rightResult);
return result;
}
void update(int node, int b, int e, int pos, int oldValue, int newValue) {
if (pos > e || pos < b) return;
if (b == e) {
if (oldValue != newValue) {
tree[node].freqCount[oldValue]--;
if (tree[node].freqCount[oldValue] == 0) {
tree[node].freqCount[oldValue] = 0;
}
tree[node].freqCount[newValue]++;
tree[node].maxFreq = tree[node].freqCount[newValue];
tree[node].minValWithMaxFreq = newValue;
}
return;
}
int mid = (b + e) / 2;
int left = node * 2;
int right = node * 2 + 1;
if (pos <= mid) {
update(left, b, mid, pos, oldValue, newValue);
} else {
update(right, mid + 1, e, pos, oldValue, newValue);
}
tree[node].merge(tree[left], tree[right]);
}
void solve() {
cin >> n;
for (int i = 1; i <= n; i++) cin >> a[i];
for (int i = 1; i < n; i++) {
int u, v;
cin >> u >> v;
Edge[u].push_back(v);
Edge[v].push_back(u);
}
DFS(1, -1);
cin >> q;
init(1, 1, n);
for (int i = 0; i < q; i++) {
int ty, node;
cin >> ty >> node;
int l = discovery_time[node];
int r = finishing_time[node];
if (ty == 1) {
char newChar;
cin >> newChar;
int val = charToIndex(newChar);
int oldValue = arr[l];
update(1, 1, n, l, oldValue, val);
arr[l] = val;
} else {
cout << indexToChar(query(1, 1, n, l, r).minValWithMaxFreq) << "\n";
}
}
}
int main() {
__Heart__
//READ("input15.txt");
//WRITE("output15.txt") ;
int t = 1; while (t--) solve();
}