题目链接 : https://vjudge.net/problem/SPOJ-COT2
/*
spojCount on a tree II
树上莫队
*/
#include<cstdio>
#include<algorithm>
#include<iostream>
#include<cmath>
#include<cstdlib>
#include<cstring>
#include<string>
#include<map>
#include<vector>
#include<set>
#include<queue>
using namespace std;
#define ll long long
const int ding=1e5+3;
vector<int>mp[ding];
int a[ding],date[ding],fa[ding],son[ding],siz[ding],top[ding],st[ding],pot[ding],ed[ding];
int deep[ding],block[ding],out[ding],vis[ding],used[ding];
int tot=1,edtot=1,ans=0;
struct Query{
int l,r,ID,lca;
}q[ding];
bool cmp(Query a,Query b){
if(block[a.l]==block[b.l]){
return a.r<b.r;
}
else return block[a.l]<block[b.l];
}
//离散化 不然会很大
void quc(int n){
int i;
sort(date+1,date+1+n);
int cnt=unique(date+1,date+n+1)-date-1;
for(i=1;i<=n;i++){
a[i]=lower_bound(date+1,date+cnt+1,a[i])-date;
}
}
//树链剖分求top
void dfs1(int x,int _fa){
int i;
siz[x]=1;
st[x]=tot++,pot[tot-1]=x;
fa[x]=_fa;
for(i=0;i<mp[x].size();i++){
int to=mp[x][i];
if(deep[to])continue;
deep[to]=deep[x]+1;
dfs1(to,x);
siz[x]+=siz[to];
if(siz[to]>siz[son[x]])son[x]=to;
}
ed[x]=tot++,pot[tot-1]=x;
}
//树链剖分求top
void dfs2(int x,int topfa){
// cout<<"x "<<x<<endl;
int i;
top[x]=topfa;
if(!son[x])return;
dfs2(son[x],topfa);
for(i=0;i<mp[x].size();i++){
int to=mp[x][i];
if(!top[to])
dfs2(to,to);
}
}
int getLca(int x,int y){
while(top[x]!=top[y]){
if(deep[top[x]]<deep[top[y]])swap(x,y);
x=fa[top[x]];
}
return deep[x]>deep[y]?y:x;
}
void dealAsk(int _q){
int i,x,y;
for(i=1;i<=_q;i++){
// cout<<"i "<<i<<endl;
scanf("%d %d",&x,&y);
// cout<<"st "<<st[x]<<" "<<st[y]<<endl;
if(st[x]>st[y])swap(x,y);
int cnt=getLca(x,y);
if(x==cnt) {
q[i].l=st[x];
q[i].r=st[y];
}
else{
q[i].l=ed[x];
q[i].r=st[y];
q[i].lca=cnt;
}
q[i].ID=i;
}
}
void add(int x){
if(vis[x]==0)ans++;
vis[x]++;
}
void del(int x){
if(vis[x]==1)ans--;
vis[x]--;
}
void Add(int x){
if(used[x])del(a[x]);
else add(a[x]);
used[x]^=1;
}
void Mo(int _q){
int i,l=1,r=0;
sort(q+1,q+_q+1,cmp);
for(i=1;i<=_q;i++){
// cout<<" qqq "<<q[i].l<<" "<<q[i].r<<endl;
while(l<q[i].l)Add(pot[l]),l++;
while(l>q[i].l)l--,Add(pot[l]);
while(r<q[i].r)r++,Add(pot[r]);
while(r>q[i].r)Add(pot[r]),r--;
if(q[i].lca)Add(q[i].lca);
out[q[i].ID]=ans;
if(q[i].lca)Add(q[i].lca);
}
for(i=1;i<=_q;i++)printf("%d\n",out[i]);
}
int main()
{
std::ios::sync_with_stdio(false);
int n,q,i,u,v;
scanf("%d %d",&n,&q);
int blo=sqrt(n);
for(i=1;i<=n;i++) {
scanf("%d",&a[i]);
date[i]=a[i];
}
for(i=1;i<=2*n;i++){
block[i]=(i-1)/blo+1;
}
quc(n);
for(i=1;i<n;i++){
scanf("%d %d",&u,&v);
mp[u].push_back(v);
mp[v].push_back(u);
}
deep[1]=1;
dfs1(1,0);
dfs2(1,1);//cout<<"qqqqq"<<endl;
dealAsk(q);
Mo(q);
return 0;
}