#include <iostream>
#include <vector>
#include <cmath>
using namespace std;
#define lc v<<1
#define rc (v<<1)+1
int timer, k;
vector<int> tin, tout, depth;
vector<vector<int>> ancestors, adj;
void dfs(int v, int p){
tin[v] = ++timer;
ancestors[v][0] = p;
depth[v] = depth[p]+1;
for(int i = 1; i <= k; i++)
ancestors[v][i] = ancestors[ancestors[v][i-1]][i-1];
for(auto u : adj[v])
if(u != p)
dfs(u,v);
tout[v] = ++timer;
}
int is_ancestor(int u, int v){
return tin[u] <= tin[v] && tout[u] >= tout[v];
}
int lca(int u, int v){
if(is_ancestor(u,v))
return u;
if(is_ancestor(v,u))
return v;
for(int i = k; i >= 0; i--)
if(!is_ancestor(ancestors[u][i],v))
u = ancestors[u][i];
return ancestors[u][0];
}
int distance(int u, int v){
return depth[u] + depth[v] - 2*depth[lca(u,v)];
}
// leaf nodes store values for tourists
// higher level nodes store pending updates
// city value is set, opinion is added
// tree supports range updates and point queries
struct node {
int city;
long long opinion;
};
struct stree {
vector<node>tree;
stree(vector<int> &arr){
tree.assign(4*(arr.size()-1),node());
build(1,1,arr.size()-1,arr);
}
void build(int v, int tl, int tr, vector<int> &arr){
if(tl == tr){
tree[v].city = arr[tl];
}else{
int tm = (tl+tr)>>1;
build(lc,tl,tm,arr);
build(rc, tm+1,tr,arr);
pushup(v);
}
}
void pushup(int v){
tree[v] = combine(tree[lc],tree[rc]);
}
node combine(node left, node right){
node rtn;
rtn.city = left.city == right.city ? left.city : 0;
rtn.opinion = 0;
return rtn;
}
void set_city(int v, int tl, int tr, int l, int r, int new_val){
if(l > tr || r < tl)
return;
if(l <= tl && r >= tr){
if(tree[v].city){
tree[v].opinion -= distance(tree[v].city, new_val);
tree[v].city = new_val;
return;
}
}
pushdown(v);
int tm = (tl+tr)>>1;
set_city(lc, tl, tm, l,r,new_val);
set_city(rc, tm+1,tr,l,r,new_val);
pushup(v);
}
void pushdown(int v){
if(tree[v].city){
tree[lc].city = tree[rc].city = tree[v].city;
tree[v].city = 0;
}
if(tree[v].opinion){
tree[lc].opinion += tree[v].opinion;
tree[rc].opinion += tree[v].opinion;
tree[v].opinion = 0;
}
}
node get(int v, int tl, int tr, int pos){
if(tl == tr){
return tree[v];
}else{
pushdown(v);
int tm = (tl+tr)>>1;
if(pos <= tm)
return get(lc,tl,tm,pos);
else
return get(rc,tm+1,tr,pos);
}
}
};
int main(){
//freopen("in.txt","r", stdin);
int n, m, q;
cin >> n >> m >> q;
vector<int> a(m+1);
for(int i = 1; i <= m; i++)
cin >> a[i];
adj.assign(n+1,vector<int>());
for(int i = 0; i < n-1; i++){
int u, v;
cin >> u >> v;
adj[u].push_back(v);
adj[v].push_back(u);
}
tin.assign(n+1,0);
tout.assign(n+1,0);
depth.assign(n+1,0);
k = ceil(log2(n));
ancestors.assign(n+1,vector<int>(k+1));
dfs(1,1);
stree tourists(a);
while(q--){
char qtype;
cin >> qtype;
if(qtype == 't'){
int f,g,c;
cin >> f >> g >> c;
tourists.set_city(1,1,m,f,g,c);
}else if(qtype == 'e'){
int c, d;
cin >> c >> d;
//not implemented
}else if(qtype == 'q'){
int v;
cin >> v;
cout << tourists.get(1,1,m,v).opinion << '\n';
}
}
return 0;
}