/*错误报告:在ICA时计算节点差值把 deep[x1]-deep[x2]写成了 x1-x2
在计算二进制数位时 sum*=2写成了sum*2
*/
#include<bits/stdc++.h>
using namespace std;
const int maxn=200100;
int n,m;//n个节点 m次询问
long long col[maxn];
int u[maxn];
int v[maxn];
int fir[maxn];
int next[maxn];
int deep[maxn];//表示节点深度
struct node//查询结构体
{
int qu,qv,w;//第w次查询,因为后面要排序
}q[maxn];
int ans[maxn];//记录每次查询答案
int ol[2*maxn];//欧拉欧拉
int cnt=0;//欧拉欧拉的长度
int in[maxn];
int out[maxn];
int len;
int inl,inr;
int book[maxn];//记录当前区间内每种颜色的数量
int book2[maxn];
int alcol=0;//颜色总数量
int fa[maxn][20];//fa[i][j]表示i节点的第2^j个父亲
void read()
{
cin>>n>>m;
for(int i=1;i<=n;i++)cin>>col[i];
for(int i=1;i<=n-1;i++)
{
cin>>u[i]>>v[i];
fa[v[i]][0]=u[i];//数组初始化
next[i]=fir[u[i]];
fir[u[i]]=i;
}
for(int i=1;i<=m;i++)//将查询储存起来
cin>>q[i].qu>>q[i].qv,q[i].w=i;
len=sqrt(2*n);//一般块的大小啦
}
long long log2(int x)//求x的二进制 数位-1
{
long long sum=1;
long long hg=0;
while(sum<=x)
sum*=2,hg++;
return hg-1;
}
void dfs(int x)
{
//树上倍增
for(int i=1;;i++)
if(fa[x][i-1])fa[x][i]=fa[fa[x][i-1]][i-1];
else break;
//深度处理
deep[x]=deep[fa[x][0]]+1;
ol[++cnt]=x;//进入标记
in[x]=cnt;
int c=fir[x];
while(c!=0)
{
dfs(v[c]);
c=next[c];
}
ol[++cnt]=x;//退出标记
out[x]=cnt;
}
bool cmp(node a,node b)//排序函数
{
return a.qu/len==b.qu/len ? a.qv<b.qv : a.qu/len < b.qu/len ;
}
void px()
{
sort(q+1,q+1+m,cmp);
}
void add(int x)
{
if(++book2[ol[x]]!=2)book[col[ol[x]]]++;//颜色++
else book[col[ol[x]]]--,book2[ol[x]]=0;//颜色减少并且退出这个点
if(book[col[ol[x]]]==0)alcol--;
if(book[col[ol[x]]]==1)alcol++;
}
void del(int x)
{
if(--book2[ol[x]]!=-1)book[col[ol[x]]]--;
else book[col[ol[x]]]++,book2[ol[x]]=1;//颜色增加并且点进入了
if(book[col[ol[x]]]==0)alcol--;
if(book[col[ol[x]]]==1)alcol++;
}
void moder()
{
for(int i=1;i<=m;i++)
{
int graf;
int l,r;
//先判断两点的情况
int x1=q[i].qu,x2=q[i].qv;
if(deep[x1]>deep[x2])
{
int cha=deep[x1]-deep[x2];//x1需要向上提x1-x2位
long long ttttt=log2(cha);
for(int i=0;i<=ttttt;i++)
if((1<<i)&cha)x1=fa[x1][i];
}
if(deep[x1]<deep[x2])
{
int cha=deep[x2]-deep[x1];//x2需要向上提x2-x1位
long long ttt=log2(cha);
for(int i=0;i<=ttt;i++)
if((1<<i)&cha)x2=fa[x2][i];
}
if(x1!=x2)
{
//一起往上跳
for(int i=20;i>=0;i--)
if(fa[x1][i]!=fa[x2][i])
x1=fa[x1][i],x2=fa[x2][i];
graf=fa[x1][0];//graf就是要求的公共祖先了
//算出实际在序列上访问的区间
l=out[q[i].qv];
r=in[q[i].qu];
}else
{
graf=x1;//特判同一个祖先
l=in[q[i].qu];
r=in[q[i].qv];
}
if(i==1)inl=l,inr=l-1;
while(inl<l)del(inl++);
while(inl>l)add(--inl);
while(inr<r)add(++inr);
while(inr>r)del(inr--);
if(book[col[graf]]==0)//两节点有公共祖先时,祖先不会被考虑到
ans[q[i].w]=alcol+1;
else ans[q[i].w]=alcol;
}
}
void o()
{
for(int i=1;i<=m;i++)cout<<ans[i]<<'\n';
}
int main()
{
read();
dfs(1);//读入欧拉序以及树上倍增预处理
px();//将查询排序
moder();//开始moder找虐
o();
}