#include<iostream>
#include<cstdio>
#include<vector>
#include<cmath>
#include<algorithm>
using namespace std;
const int maxn=8e4+5;
int testcase,n,m,T,tot,pos,cnt,x,y,k,size_x,size_y,fx,fy,lastans,lca;
int lg[maxn],discre[maxn],root[maxn];
char c;
vector<int> v[maxn];
struct miku{
int num,depth,father[20],fa,sum;
}a[maxn];
struct t{
int lson,rson,sum;
}tree[maxn<<10];
//2¢2é?ˉ
int find(int k){
if(a[k].fa==k)
return k;
return a[k].fa=find(a[k].fa);
}
//lca
void dfs(int node,int FA){
a[node].father[0]=FA;
a[node].depth=a[FA].depth+1;
for(int i=1;i<=lg[a[node].depth];i++)
a[node].father[i]=a[a[node].father[i-1]].father[i-1];
for(int i=0;i<v[node].size();i++)
if(v[node][i]!=FA)
dfs(v[node][i],node);
return ;
}
int LCA(int u,int v){
if(a[u].depth<a[v].depth)
swap(u,v);
while(a[u].depth>a[v].depth)
u=a[u].father[lg[a[u].depth-a[v].depth]-1];
if(u==v)
return u ;
for(int i=lg[a[u].depth]-1;i>=0;i--){
if(a[u].father[i]!=a[v].father[i]){
u=a[u].father[i];
v=a[v].father[i];
}
}
return a[u].father[0];
}
//????ê÷
int build(int l,int r){
int node=++cnt;
int mid=(l+r)>>1;
if(l<r){
build(l,mid);
build(mid+1,r);
}
return node;
}
int update(int node1,int node2,int l,int r,int aim){
if(!node1)
node1=++cnt;
tree[node1].sum=tree[node2].sum+1;
tree[node1].lson=tree[node2].lson;
tree[node1].rson=tree[node2].rson;
if(l<r){
int mid=(l+r)>>1;
if(aim<=mid)
tree[node1].lson=update(tree[node1].lson,tree[node2].lson,l,mid,aim);
else
tree[node1].rson=update(tree[node1].rson,tree[node2].rson,mid+1,r,aim);
}
return node1;
}
int merge(int node1,int node2,int l,int r){
if(!node1)
return node2;
if(!node2)
return node1;
if(l==r){
tree[node1].sum+=tree[node2].sum;
return node1;
}
int mid=(l+r)>>1;
if(l<r){
tree[node1].lson=merge(tree[node1].lson,tree[node2].lson,l,mid);
tree[node1].rson=merge(tree[node1].rson,tree[node2].rson,mid+1,r);
tree[node1].sum=tree[tree[node1].lson].sum+tree[tree[node1].rson].sum;
}
return node1;
}
void change(int node,int FA){
for(int i=0;i<v[node].size();i++)
if(v[node][i]!=FA){
root[v[node][i]]=update(root[v[node][i]],root[node],1,tot,a[v[node][i]].num);
change(v[node][i],node);
}
return ;
}
int query(int node1,int node2,int node3,int node4,int l,int r,int k){
if(l==r)
return l;
int mid=(l+r)>>1;
int SUM=tree[tree[node3].lson].sum+tree[tree[node4].lson].sum-tree[tree[node1].lson].sum-tree[tree[node2].lson].sum;
// cout<<SUM<<endl;
if(SUM>=k)
return query(tree[node1].lson,tree[node2].lson,tree[node3].lson,tree[node4].lson,l,mid,k);
else
return query(tree[node1].rson,tree[node2].rson,tree[node3].rson,tree[node4].rson,mid+1,r,k-SUM);
}
void print(int node,int l,int r){
printf("%d %d %d\n",l,r,tree[node].sum);
int mid=(l+r)>>1;
if(l<r){
print(tree[node].lson,l,mid);
print(tree[node].rson,mid+1,r);
}
}
int main(){
scanf("%d",&testcase);
scanf("%d%d%d",&n,&m,&T);
for(int i=1;i<=n;i++)
lg[i]=int(log2(i))+1;
for(int i=1;i<=n;i++){
scanf("%d",&a[i].num);
dfs(i,0);
a[i].fa=i;
a[i].sum=1;
discre[i]=a[i].num;
}
sort(discre+1,discre+n+1);
tot=unique(discre+1,discre+n+1)-(discre+1);
root[0]=build(1,tot);
for(int i=1;i<=n;i++){
pos=lower_bound(discre+1,discre+tot+1,a[i].num)-discre;
root[i]=update(root[i],root[0],1,tot,pos);
// print(root[i],1,tot);
// cout<<endl;
}
for(int i=1;i<=m;i++){
scanf("%d%d",&x,&y);
// cout<<endl;
v[x].push_back(y);
v[y].push_back(x);
fx=find(a[x].fa);
fy=find(a[y].fa);
size_x=a[fx].sum;
size_y=a[fy].sum;
if(size_x<size_y){
a[fy].sum+=a[fx].sum;
a[fx].sum=0;
a[fx].fa=fy;
dfs(fx,y);
// print(root[y],1,tot);
// cout<<endl;
root[fx]=merge(root[fx],root[y],1,tot);
// printf("%d %d\n",fx,y);
// print(root[fx],1,tot);
// cout<<endl;
// print(root[y],1,tot);
// cout<<endl;
change(fx,a[fx].father[0]);
}
else{
a[fx].sum+=a[fy].sum;
a[fy].sum=0;
a[fy].fa=fx;
dfs(fy,x);
// print(root[fy],1,tot);
// cout<<endl;
root[fy]=merge(root[fy],root[x],1,tot);
// printf("%d %d\n",fy,x);
// print(root[fy],1,tot);
// cout<<endl;
// print(root[x],1,tot);
// cout<<endl;
change(fy,a[fy].father[0]);
}
}
// for(int i=1;i<=n;i++)
// cout<<a[i].fa<<' ';
// cout<<endl;
// for(int i=1;i<=n;i++){
// print(root[i],1,tot);
// cout<<endl;
// }
while(T--){
cin>>c;
if(c=='Q'){
scanf("%d%d%d",&x,&y,&k);
x=x^lastans;
y=y^lastans;
k=k^lastans;
// cout<<x<<' '<<y<<' '<<k<<endl;
lca=LCA(x,y);
// cout<<lca<<endl;
lastans=discre[query(root[lca],root[a[lca].father[0]],root[x],root[y],1,tot,k)];
printf("%d\n",lastans);
}
else{
scanf("%d%d",&x,&y);
x=x^lastans;
y=y^lastans;
// cout<<x<<' '<<y<<endl;
v[x].push_back(y);
v[y].push_back(x);
fx=find(a[x].fa);
fy=find(a[y].fa);
size_x=a[fx].sum;
size_y=a[fy].sum;
// cout<<fx<<' '<<fy<<endl;
if(size_x<size_y){
a[fy].sum+=a[fx].sum;
a[fx].sum=0;
a[fx].fa=fy;
dfs(fx,y);
// print(root[y],1,tot);
// cout<<endl;
root[fx]=merge(root[fx],root[y],1,tot);
// printf("%d %d\n",fx,y);
// print(root[fx],1,tot);
// cout<<endl;
// print(root[y],1,tot);
// cout<<endl;
change(fx,a[fx].father[0]);
}
else{
a[fx].sum+=a[fy].sum;
a[fy].sum=0;
a[fy].fa=fx;
dfs(fy,x);
// print(root[fy],1,tot);
// cout<<endl;
root[fy]=merge(root[fy],root[x],1,tot);
// printf("%d %d\n",fy,x);
// print(root[fy],1,tot);
// cout<<endl;
// print(root[x],1,tot);
// cout<<endl;
change(fy,a[fy].father[0]);
}
}
}
return 0;
}