#include<cstdio>
#include<cstring>
#include<algorithm>
#include<vector>
#define OPT __attribute__((optimize("O2")))
using namespace std;
typedef unsigned long long ll;
template <typename T>
OPT inline void read(T &x){
T f=1;char ch=getchar();x=0;
while(ch<‘0‘||ch>‘9‘){if(ch==‘-‘)f=-1;ch=getchar();}
while(ch>=‘0‘&&ch<=‘9‘){x=x*10+ch-‘0‘;ch=getchar();}
x*=f;
}
const ll inf=~0ULL;
const int N=1e5+5,M=480,T=7e5+5;
struct edge{int v,next;}e[N<<1];int tot=1,head[N];
struct P{
int x,y,d,o;
P(){}
P(int _x,int _y,int _d,int _o){
x=_x;y=_y;d=_d;o=_o;
}
};
int n,m,type,mx,sum,root;
int A,B,last;
int a[N],b[N];
int f[N],siz[N],dep[N];bool vis[N];
int cnt,cur[30],pos[T][30];
ll pool[T][16],bit[M];
vector<P>G[N];
OPT inline bool cmp(const P &c,const P &d){//按子树根节点排序
return c.x<d.x;
}
OPT inline void add(int x,int y){
e[++tot].v=y;e[tot].next=head[x];head[x]=tot;
e[++tot].v=x;e[tot].next=head[y];head[y]=tot;
}
OPT inline void findroot(int x,int fa){//找重心
siz[x]=1;f[x]=0;
for(int i=head[x];i;i=e[i].next){
if(vis[e[i].v]||e[i].v==fa) continue;
findroot(e[i].v,x);
siz[x]+=siz[e[i].v];
f[x]=max(f[x],siz[e[i].v]);
}
f[x]=max(f[x],sum-siz[x]);
if(f[x]<f[root]) root=x;
}
//对于每个点
//记录(重心,重心到它第一个点,距离,可持久)
OPT inline void getdep(int x,int y,int z){//算深度
f[x]=y;dep[x]=z;
if(z>mx) mx=z;
for(int i=head[x];i;i=e[i].next){
if(vis[e[i].v]||e[i].v==y) continue;
getdep(e[i].v,x,z+1);
}
}
//30块,每块16个数
OPT inline void dfs1(int x,int y,int z){
if(y==root) z=x;
//修改第b[x]个位置
//把bitset的第b[x]>>4个位置的第b[x]&15或上1ULL<<(a[x]&63)
int t=cur[b[x]>>4];
cur[b[x]>>4]=++cnt;
for(int i=0;i<16;i++) pool[cnt][i]=pool[t][i];
pool[cnt][b[x]&15]|=1ULL<<(a[x]&63);
for(int i=0;i<30;i++) pos[cnt][i]=cur[i];
G[x].push_back(P(root,z,dep[x],cnt));
for(int i=head[x];i;i=e[i].next){
if(vis[e[i].v]||e[i].v==y) continue;
dfs1(e[i].v,x,z);
}
cur[b[x]>>4]=t;//还原
}
OPT inline void dfs2(int x,int y,int z){
if(y==root) z=x;
G[x].push_back(P(root,z,dep[x],0));
for(int i=head[x];i;i=e[i].next){
if(vis[e[i].v]||e[i].v==y) continue;
dfs2(e[i].v,x,z);
}
}
OPT inline void solve(int x){
vis[x]=1;mx=0;
getdep(x,0,0);
if(mx>M) dfs1(x,0,0);else dfs2(x,0,0);
for(int i=head[x];i;i=e[i].next){
if(vis[e[i].v]) continue;
f[0]=sum=siz[e[i].v];findroot(e[i].v,root=0);solve(root);
}
}
OPT inline void visit(int x){//标记状态,即某颜色是否出现了
x=a[x];
bit[x>>6]|=1ULL<<(x&63);
}
OPT inline void chain(int x,int y,int d,int o){//统计x->y这条链状态
if(d>M){
for(int i=0;i<30;i++)
for(int j=0,k=pos[o][i];j<16;j++)
bit[i<<4|j]|=pool[k][j];
return ;
}
for(;x!=y;x=f[x]){
if(dep[x]<dep[y]) swap(x,y);
visit(x);
}
visit(x);
}
OPT inline void work(int x,int y){//拆成链
if(x==y){visit(x);return ;}
vector<P>::iterator i=G[x].begin(),j=G[y].begin();
vector<P>::iterator p=G[x].end(),q=G[y].end();
while(i!=p&&j!=q){
if(i->x<j->x){i++;continue;}
if(i->x>j->x){j++;continue;}
if(i->y==j->y){i++;j++;continue;}
if(i->x!=x) chain(x,i->x,i->d,i->o);
if(i->x!=y) chain(y,j->x,j->d,j->o);
i++;j++;
}
}
OPT inline int ask(){//直接查询有多少个“1”
int res=0;
for(int i=0;i<M;i++) res+=__builtin_popcountll(bit[i]);
return res;
}
OPT inline int mex(){//按块枚举
for(int i=0;;i++) if(bit[i]!=inf)
for(int j=0;;j++) if(bit[i]>>j&1^1)
return (i<<6)|j;
}
OPT inline void DFS(int x,int y){//点分治之后,还原树
dep[x]=dep[y]+1;f[x]=y;
for(int i=head[x];i;i=e[i].next){
if(e[i].v==y) continue;
DFS(e[i].v,x);
}
}
OPT int main(){
read(n);read(m),read(type);
for(int i=1;i<=n;i++) read(a[i]),b[i]=a[i]>>6;;//0<=a[i]<=30000
for(int i=1,x,y;i<n;i++) read(x),read(y),add(x,y);
f[0]=sum=n;findroot(1,root=0);solve(root);
for(int i=1;i<=n;i++) sort(G[i].begin(),G[i].end(),cmp);
DFS(1,0);
for(int k,x,y;m--;memset(bit,0,sizeof bit)){
for(read(k);k--;){
read(x);read(y);
if(type) x^=last,y^=last;
work(x,y);
}
A=ask();B=mex();
printf("%d %d\n",A,B);
last=A+B;
}
return 0;
}