#include<bits/stdc++.h>
using namespace std;
typedef double db;
typedef long long ll;
typedef vector<int> vi;
typedef pair<int, int> pii;
#define endl "\n"
#define fi first
#define se second
#define mp make_pair
#define pb push_back
#define pw(x) (1ll << (x))
#define sz(x) ((int)(x).size())
#define all(x) (x).begin(),(x).end()
#define rep(i,l,r) for(int i=(l);i<(r);++i)
#define per(i,l,r) for(int i=(r)-1;i>=(l);--i)
#define dd(x) cout << #x << " = " << x << ", "
#define de(x) cout << #x << " = " << x << endl
//-----
const int N=2e5+7;
pii data[N];
int dfn[N],st[N],ed[N],zt[N],Fa[20][N],Dep[N];
int Index=0,B=sqrt(2e5);
vector<int> V[N];
ll res[N],Ans=0;
ll boy[N],girl[N];
void dfs(int a,int fa,int dep) {
	st[a]=++Index,dfn[Index]=a;Fa[0][a]=fa;Dep[a]=dep;
	rep(i,0,sz(V[a])) {
		int nxt=V[a][i];
		if(nxt==fa)continue;
		dfs(nxt,a,dep+1);
	}
	ed[a]=++Index,dfn[Index]=a;
}
struct Query {
	int l,r,id,Lca;
	Query(int _l=0,int _r=0,int _id=0,int _Lca=0) {
		l=_l,r=_r,id=_id;Lca=_Lca;
	}
}qry[N];
int cmp(Query a,Query b) {
	if(a.l/B!=b.l/B)return a.l<b.l;
	return a.r<b.r;
}
void Add(int id) {
	pii now=data[id];
	Ans-=boy[now.se]*girl[now.se];
	if(now.fi==1)boy[now.se]++;
	else girl[now.se]++;
	Ans+=boy[now.se]*girl[now.se];
}
void Del(int id) {
	pii now=data[id];
	Ans-=boy[now.se]*girl[now.se];
	if(now.fi==1)boy[now.se]--;
	else girl[now.se]--;
	Ans+=boy[now.se]*girl[now.se];
}
void upd(int pos) {
	int id=dfn[pos];
	if(zt[id]==0)Add(id);
	else Del(id);
	zt[id]^=1;
}
int lca(int a,int b)
{
    if(Dep[a]<Dep[b])swap(a,b);
    per(i,0,20)if((1<<i)<=Dep[a]-Dep[b])a=Fa[i][a];
    if(a==b)return a;
    per(i,0,20)if(Fa[i][a]!=Fa[i][b])a=Fa[i][a],b=Fa[i][b];
    assert(Fa[0][a]==Fa[0][b]);
    return Fa[0][a];
}
vector<int> v;
int main() {
	int n;scanf("%d",&n);
	rep(i,1,n+1)scanf("%d",&data[i].fi);
	rep(i,1,n+1)scanf("%d",&data[i].se),v.pb(data[i].se);
	sort(all(v));v.erase(unique(all(v)),v.end());
	rep(i,1,n+1)data[i].se=lower_bound(all(v),data[i].se)-v.begin()+1;
	rep(i,1,n) {
		int a,b;scanf("%d%d",&a,&b);
		V[a].pb(b);
		V[b].pb(a);
	}
	dfs(1,0,1);
	rep(i,1,20)rep(j,1,n+1)Fa[i][j]=Fa[i-1][Fa[i-1][j]];
	int q;scanf("%d",&q);
	rep(i,0,q) {
		int a,b;scanf("%d%d",&a,&b);
		int Lca=lca(a,b);
		if(Lca==a)qry[i]=Query(st[a],st[b],i);
		else if(Lca==b)qry[i]=Query(st[b],st[a],i);
		else if(st[a]>st[b])qry[i]=Query(ed[b],st[a],i,Lca);
		else qry[i]=Query(ed[a],st[b],i,Lca);
	}
	sort(qry,qry+q,cmp);
	int l=1,r=0;
	rep(i,0,q) {
		while(r<qry[i].r)upd(++r);
		while(l>qry[i].l)upd(--l);
		while(r>qry[i].r)upd(r--);
		while(l<qry[i].l)upd(l++);
		if(qry[i].Lca)Add(qry[i].Lca);
		res[qry[i].id]=Ans;
		if(qry[i].Lca)Del(qry[i].Lca);
	}
	rep(i,0,q)cout<<res[i]<<endl;
	return 0;
}


#include<bits/stdc++.h>
using namespace std;
typedef double db;
typedef long long ll;
typedef vector<int> vi;
typedef pair<int, int> pii;
#define endl "\n"
#define fi first
#define se second
#define mp make_pair
#define pb push_back
#define pw(x) (1ll << (x))
#define sz(x) ((int)(x).size())
#define all(x) (x).begin(),(x).end()
#define rep(i,l,r) for(int i=(l);i<(r);++i)
#define per(i,l,r) for(int i=(r)-1;i>=(l);--i)
#define dd(x) cout << #x << " = " << x << ", "
#define de(x) cout << #x << " = " << x << endl
//-----
const int N=2e5+7;
pii data[N];
int dfn[N],st[N],ed[N],zt[N],Fa[20][N],Dep[N];
int Index=0,B=sqrt(2e5);
vector<int> V[N];
ll res[N],Ans=0;
ll boy[N],girl[N];
void dfs(int a,int fa,int dep) {
	st[a]=++Index,dfn[Index]=a;Fa[0][a]=fa;Dep[a]=dep;
	rep(i,0,sz(V[a])) {
		int nxt=V[a][i];
		if(nxt==fa)continue;
		dfs(nxt,a,dep+1);
	}
	ed[a]=++Index,dfn[Index]=a;
}
struct Query {
	int l,r,id,Lca;
	Query(int _l=0,int _r=0,int _id=0,int _Lca=0) {
		l=_l,r=_r,id=_id;Lca=_Lca;
	}
}qry[N];
int cmp(Query a,Query b) {
	if(a.l/B!=b.l/B)return a.l<b.l;
	return a.r<b.r;
}
void Add(int id) {
	pii now=data[id];
	Ans-=boy[now.se]*girl[now.se];
	if(now.fi==1)boy[now.se]++;
	else girl[now.se]++;
	Ans+=boy[now.se]*girl[now.se];
}
void Del(int id) {
	pii now=data[id];
	Ans-=boy[now.se]*girl[now.se];
	if(now.fi==1)boy[now.se]--;
	else girl[now.se]--;
	Ans+=boy[now.se]*girl[now.se];
}
void upd(int pos) {
	int id=dfn[pos];
	if(zt[id]==0)Add(id);
	else Del(id);
	zt[id]^=1;
}
int lca(int a,int b)
{
    if(Dep[a]<Dep[b])swap(a,b);
    per(i,0,20)if((1<<i)<=Dep[a]-Dep[b])a=Fa[i][a];
    if(a==b)return a;
    per(i,0,20)if(Fa[i][a]!=Fa[i][b])a=Fa[i][a],b=Fa[i][b];
    assert(Fa[0][a]==Fa[0][b]);
    return Fa[0][a];
}
vector<int> v;
int main() {
	int n;scanf("%d",&n);
	rep(i,1,n+1)scanf("%d",&data[i].fi);
	rep(i,1,n+1)scanf("%d",&data[i].se),v.pb(data[i].se);
	sort(all(v));v.erase(unique(all(v)),v.end());
	rep(i,1,n+1)data[i].se=lower_bound(all(v),data[i].se)-v.begin()+1;
	rep(i,1,n) {
		int a,b;scanf("%d%d",&a,&b);
		V[a].pb(b);
		V[b].pb(a);
	}
	dfs(1,0,1);
	rep(i,1,20)rep(j,1,n+1)Fa[i][j]=Fa[i-1][Fa[i-1][j]];
	int q;scanf("%d",&q);
	rep(i,0,q) {
		int a,b;scanf("%d%d",&a,&b);
		int Lca=lca(a,b);
		if(st[a]>st[b])qry[i]=Query(ed[b],st[a],i,Lca);
		else qry[i]=Query(ed[a],st[b],i,Lca);
	}
	sort(qry,qry+q,cmp);
	int l=1,r=0;
	rep(i,0,q) {
		while(r<qry[i].r)upd(++r);
		while(l>qry[i].l)upd(--l);
		while(r>qry[i].r)upd(r--);
		while(l<qry[i].l)upd(l++);
		Add(qry[i].Lca);
		res[qry[i].id]=Ans;
		Del(qry[i].Lca);
	}
	rep(i,0,q)cout<<res[i]<<endl;
	return 0;
}


#include<bits/stdc++.h>
using namespace std;
typedef double db;
typedef long long ll;
typedef vector<int> vi;
typedef pair<int, int> pii;
#define endl "\n"
#define fi first
#define se second
#define mp make_pair
#define pb push_back
#define pw(x) (1ll << (x))
#define sz(x) ((int)(x).size())
#define all(x) (x).begin(),(x).end()
#define rep(i,l,r) for(int i=(l);i<(r);++i)
#define per(i,l,r) for(int i=(r)-1;i>=(l);--i)
#define dd(x) cout << #x << " = " << x << ", "
#define de(x) cout << #x << " = " << x << endl
//-----
const int N=2e5+7;
pii data[N];
int dfn[N],st[N],ed[N],zt[N],Fa[20][N],Dep[N];
int Index=0,B=sqrt(2e5);
vector<int> V[N];
ll res[N],Ans=0;
int boy[N],girl[N];
void dfs(int a,int fa,int dep) {
	st[a]=++Index,dfn[Index]=a;Fa[0][a]=fa;Dep[a]=dep;
	rep(i,0,sz(V[a])) {
		int nxt=V[a][i];
		if(nxt==fa)continue;
		dfs(nxt,a,dep+1);
	}
	ed[a]=++Index,dfn[Index]=a;
}
struct Query {
	int l,r,id,Lca;
	Query(int _l=0,int _r=0,int _id=0,int _Lca=0) {
		l=_l,r=_r,id=_id;Lca=_Lca;
	}
}qry[N];
int cmp(Query a,Query b) {
	if(a.l/B!=b.l/B)return a.l<b.l;
	return a.r<b.r;
}
void Add(int id) {
	pii now=data[id];
	Ans-=boy[now.se]*girl[now.se];
	if(now.fi==1)boy[now.se]++;
	else girl[now.se]++;
	Ans+=boy[now.se]*girl[now.se];
}
void Del(int id) {
	pii now=data[id];
	Ans-=boy[now.se]*girl[now.se];
	if(now.fi==1)boy[now.se]--;
	else girl[now.se]--;
	Ans+=boy[now.se]*girl[now.se];
}
void upd(int pos) {
	int id=dfn[pos];
	if(zt[id]==0)Add(id);
	else Del(id);
	zt[id]^=1;
}
int lca(int a,int b)
{
    if(Dep[a]<Dep[b])swap(a,b);
    per(i,0,20)if((1<<i)<=Dep[a]-Dep[b])a=Fa[i][a];
    if(a==b)return a;
    per(i,0,20)if(Fa[i][a]!=Fa[i][b])a=Fa[i][a],b=Fa[i][b];
    assert(Fa[0][a]==Fa[0][b]);
    return Fa[0][a];
}
vector<int> v;
int main() {
	int n;scanf("%d",&n);
	rep(i,1,n+1)scanf("%d",&data[i].fi);
	rep(i,1,n+1)scanf("%d",&data[i].se),v.pb(data[i].se);
	sort(all(v));v.erase(unique(all(v)),v.end());
	rep(i,1,n+1)data[i].se=lower_bound(all(v),data[i].se)-v.begin()+1;
	rep(i,1,n) {
		int a,b;scanf("%d%d",&a,&b);
		V[a].pb(b);
		V[b].pb(a);
	}
	dfs(1,0,1);
	rep(i,1,20)rep(j,1,n+1)Fa[i][j]=Fa[i-1][Fa[i-1][j]];
	int q;scanf("%d",&q);
	rep(i,0,q) {
		int a,b;scanf("%d%d",&a,&b);
		int Lca=lca(a,b);
		if(Lca==a)qry[i]=Query(st[a],st[b],i);
		else if(Lca==b)qry[i]=Query(st[b],st[a],i);
		else if(st[a]>st[b])qry[i]=Query(ed[b],st[a],i,Lca);
		else qry[i]=Query(ed[a],st[b],i,Lca);
	}
	sort(qry,qry+q,cmp);
	int l=1,r=0;
	rep(i,0,q) {
		while(r<qry[i].r)upd(++r);
		while(l>qry[i].l)upd(--l);
		while(r>qry[i].r)upd(r--);
		while(l<qry[i].l)upd(l++);
		if(qry[i].Lca)Add(qry[i].Lca);
		res[qry[i].id]=Ans;
		if(qry[i].Lca)Del(qry[i].Lca);
	}
	rep(i,0,q)cout<<res[i]<<endl;
	return 0;
}


#include <bits/stdc++.h>

#define pii pair<int, int>
#define f first
#define s second
#define pb push_back
#define mp make_pair
#define ll long long
#define ull unsigned ll
#define ld long double
#define sz(v) int(v.size())
#define all(v) v.begin(), v.end()
#define vec vector<int>

#define left not_right
#define y1 what

using namespace std;

const int N = (int) 1e5 + 10;
const int M = (int) 2e6 + 7;
const ll LINF = (ll) 1e18;
const int INF = (int) 1e9 + 7;
const double EPS = (double) 1e-9;

int n, q;

struct person {
	int type, clr;
	int tin, tout;
	vec v;

	person() {

	}
};

int dp[N][20], lvl[N];
person a[N];
vec ord;

void dfs(int x = 1, int p = -1) {
	if (p != -1) {
		lvl[x] = lvl[p] + 1;
		dp[x][0] = p;
		for (int i = 1; i < 20; i++) {
			dp[x][i] = dp[dp[x][i - 1]][i - 1];
		}
	}
	a[x].tin = sz(ord);
	ord.pb(x);
	for (auto it : a[x].v) {
		if (it - p) {
			dfs(it, x);
		}
	}
	a[x].tout = sz(ord);
	ord.pb(x);
}

int get_lca(int x, int y) {
	if (lvl[x] > lvl[y])
		swap(x, y);
	int d = lvl[y] - lvl[x];
	for (int i = 0; i < 20; i++) {
		if ((d >> i) % 2) {
			y = dp[y][i];
		}
	}
	if (x == y)
		return x;
	for (int i = 19; i >= 0; i--) {
		if (dp[x][i] != dp[y][i]) {
			x = dp[x][i];
			y = dp[y][i];
		}
	}
	return dp[x][0];
}

int main() {
    #define fn "balls"
    #ifdef witch
        freopen("input.txt", "r", stdin);
        freopen("output.txt", "w", stdout);
    #else
//        freopen(fn".in", "r", stdin);
//        freopen(fn".out", "w", stdout);
    #endif
    cin >> n;
    for (int i = 1; i <= n; i++) {
    	cin >> a[i].type;
    }
    for (int i = 1; i <= n; i++) {
    	cin >> a[i].clr;
    }
    for (int i = 1, x, y; i < n; i++) {
    	cin >> x >> y;
    	a[x].v.pb(y);
    	a[y].v.pb(x);
	}
	dfs();
	cin >> q;
	for (int i = 1; i <= q; i++) {
		int x, y;
		cin >> x >> y;
		if (lvl[x] > lvl[y])
			swap(x, y);
		int lca = get_lca(x, y);
		ll ans = 0;
		map<pii, int> cnt;
		map<int, int> occ;
		if (x == lca) {
			for (int j = a[x].tin; j <= a[y].tin; j++) {
				occ[ord[j]] ^= 1;
				if (occ[ord[j]]) {
					cnt[mp(a[ord[j]].type, a[ord[j]].clr)]++;
					ans += cnt[mp(1 - a[ord[j]].type, a[ord[j]].clr)];
				}
				else {
					cnt[mp(a[ord[j]].type, a[ord[j]].clr)]--;
					ans -= cnt[mp(1 - a[ord[j]].type, a[ord[j]].clr)];
				}
			}
		} else {
			if (a[x].tout > a[y].tin)
				swap(x, y);
			for (int j = a[x].tout; j <= a[y].tin; j++) {
				occ[ord[j]] ^= 1;
				if (occ[ord[j]]) {
					cnt[mp(a[ord[j]].type, a[ord[j]].clr)]++;
					ans += cnt[mp(1 - a[ord[j]].type, a[ord[j]].clr)];
				}
				else {
					cnt[mp(a[ord[j]].type, a[ord[j]].clr)]--;
					ans -= cnt[mp(1 - a[ord[j]].type, a[ord[j]].clr)];
				}
			}
			for (int j = a[lca].tin; j <= a[lca].tin; j++) {
				occ[ord[j]] ^= 1;
				if (occ[ord[j]]) {
					cnt[mp(a[ord[j]].type, a[ord[j]].clr)]++;
					ans += cnt[mp(1 - a[ord[j]].type, a[ord[j]].clr)];
				}
				else {
					cnt[mp(a[ord[j]].type, a[ord[j]].clr)]--;
					ans -= cnt[mp(1 - a[ord[j]].type, a[ord[j]].clr)];
				}
			}
		}
		cout << ans << endl;
	}
    return 0;
}


#include <bits/stdc++.h>

#define pii pair<int, int>
#define f first
#define s second
#define pb push_back
#define mp make_pair
#define ll long long
#define ull unsigned ll
#define ld long double
#define sz(v) int(v.size())
#define all(v) v.begin(), v.end()
#define vec vector<int>

#define left not_right
#define y1 what

using namespace std;

const int N = (int) 1e5 + 10;
const int M = (int) 2e6 + 7;
const int RAUAN = 350;
const ll LINF = (ll) 1e18;
const int INF = (int) 1e9 + 7;
const double EPS = (double) 1e-9;

int n, q;

struct person {
	int type, clr;
	int tin, tout;
	vec v;

	person() {

	}
};

int dp[N][20], lvl[N];
person a[N];
vec ord;

void dfs(int x = 1, int p = -1) {
	if (p != -1) {
		lvl[x] = lvl[p] + 1;
		dp[x][0] = p;
		for (int i = 1; i < 20; i++) {
			dp[x][i] = dp[dp[x][i - 1]][i - 1];
		}
	}
	a[x].tin = sz(ord);
	ord.pb(x);
	for (auto it : a[x].v) {
		if (it - p) {
			dfs(it, x);
		}
	}
	a[x].tout = sz(ord);
	ord.pb(x);
}

int get_lca(int x, int y) {
	if (lvl[x] > lvl[y])
		swap(x, y);
	int d = lvl[y] - lvl[x];
	for (int i = 0; i < 20; i++) {
		if ((d >> i) % 2) {
			y = dp[y][i];
		}
	}
	if (x == y)
		return x;
	for (int i = 19; i >= 0; i--) {
		if (dp[x][i] != dp[y][i]) {
			x = dp[x][i];
			y = dp[y][i];
		}
	}
	return dp[x][0];
}

struct qq {
	int l, r, id, x, y;

	qq() {

	}

	qq(int _l, int _r, int _id, int _x, int _y) {
		l = _l;
		r = _r;
		id = _id;
		x = _x;
		y = _y;
	}
};

bool cmp(qq x, qq y) {
	if (x.l / RAUAN != y.l / RAUAN)
		return x.l < y.l;
	return x.r < y.r;
}

ll ans[N];
vector<qq> query;
int c[N], cnt[2][N];
ll cur_ans;

void del(int pos) {
	int x = ord[pos];
	if (c[x]) {
		cnt[a[x].type][a[x].clr]--;
		cur_ans -= cnt[a[x].type ^ 1][a[x].clr];
	} else {
		cnt[a[x].type][a[x].clr]++;
		cur_ans += cnt[a[x].type ^ 1][a[x].clr];
	}
	c[x] ^= 1;
}

void add(int pos) {
	int x = ord[pos];
	c[x] ^= 1;
	if (c[x]) {
		cnt[a[x].type][a[x].clr]++;
		cur_ans += cnt[a[x].type ^ 1][a[x].clr];
	}
	else {
		cnt[a[x].type][a[x].clr]--;
		cur_ans -= cnt[a[x].type ^ 1][a[x].clr];
	}
	//cout << cur_ans << ' ';
}

int main() {
    #define fn "balls"
    #ifdef witch
        freopen("input.txt", "r", stdin);
        freopen("output.txt", "w", stdout);
    #else
//        freopen(fn".in", "r", stdin);
//        freopen(fn".out", "w", stdout);
    #endif
    cin >> n;
    for (int i = 1; i <= n; i++) {
    	cin >> a[i].type;
    }
    vec num;
    for (int i = 1; i <= n; i++) {
    	cin >> a[i].clr;
    	num.pb(a[i].clr);
    }
    sort(all(num));
    for (int i = 1; i <= n; i++) {
    	a[i].clr = lower_bound(all(num), a[i].clr) - num.begin();
    }
    for (int i = 1, x, y; i < n; i++) {
    	cin >> x >> y;
    	a[x].v.pb(y);
    	a[y].v.pb(x);
	}
	dfs();
	cin >> q;
	for (int i = 1; i <= q; i++) {
		int x, y;
		cin >> x >> y;
		if (lvl[x] > lvl[y])
			swap(x, y);
		int lca = get_lca(x, y);
		if (x == lca) {
			query.pb(qq(a[x].tin, a[y].tin, i, -1, -1));
		} else {
			if (a[x].tout > a[y].tin)
				swap(x, y);
			query.pb(qq(a[x].tout, a[y].tin, i, -1, -1));
			query.pb(qq(a[x].tout, a[y].tin, i, a[lca].type ^ 1, a[lca].clr));
		}
	}
	sort(all(query), cmp);
	int l = 0, r = -1;
	for (auto it : query) {
		while (l < it.l) {
			//delete l
			del(l);
			l++;
		}
		while (l > it.l) {
			l--;
			add(l);
			// add l
		}
		while (r < it.r) {
			r++;
			add(r);
			// add r
		}
		while (r > it.r) {
			// delete r
			del(r);
			r--;
		}
		/*
		cout<<endl;
		cout << it.l << ' ' << it.r << ' ' << it.id << ' ' << it.x << ' ' << it.y << "\n";
		for(int i=it.l;i<=it.r;i++)cout<<ord[i]<<' ';cout<<" => ";
		*/
		if (it.x == -1) {
		//	cout << cur_ans << endl;
			ans[it.id] += cur_ans;
		} else {
		//	cout << cnt[it.x][it.y] << endl;
			ans[it.id] += cnt[it.x][it.y];
		}
	}
	for (int i = 1; i <= q; i++) {
		cout << ans[i] << endl;
	}
    return 0;
}


#include <bits/stdc++.h>

using namespace std;

typedef long long ll;
typedef vector<int> vi;
typedef pair<int,int> ii;

#define pb push_back
#define all(x) x.begin(),x.end()
#define sz(x) (int)x.size()
#define fill(a,x) memset(a,x,sizeof(a))
#define F first
#define S second
#define FOR(i,a,b) for(int i = a; i<=b; ++i)
#define NFOR(i,a,b) for(int i = a; i>=b; --i)
#define fast ios_base::sync_with_stdio(false),cin.tie(0),cout.tie(0)
const ll INF = 1e18;
const int mod = 1e9+7;
const int N = 2e5 + 10;
inline int add(int x,int y){
  x += y;
  if(x >= mod) x -= mod;
  return x;
}
inline int mul(int x,int y){
  x = (1LL * x * y) % mod;
  return x;
}
const int ROOT = 420;
struct node{
  int l,r,e,i;
}Q[N];

bool cmp(node x,node y){
  if(x.l/ROOT!=y.l/ROOT){
    return x.l/ROOT < y.l/ROOT;
  }
  return x.r<y.r;
}
int T = 1;
vector<int> G[N];
int dep[N];
int _n = 0;
int pos[N],LCA[20][2*N];
void dfslca(int v,int p = 0,int d = 0){
  pos[v] = _n;
  dep[v] = d;
  LCA[0][_n] = v;
  _n++;
  for(int it : G[v]){
    if(it != p){
      dfslca(it,v,d+1);
    }
  }
  if(p != 0){
    LCA[0][_n] = p;
    _n++;
  }
}
void LCApre(){
  for(int i = 1; i < 20 ; ++i){
    for(int j = 0 ; j  + (1<<(i-1)) < _n; ++j){
      if(dep[LCA[i-1][j]] < dep[LCA[i-1][j+(1<<(i-1))]])LCA[i][j] = LCA[i-1][j];
      else LCA[i][j] = LCA[i-1][j+(1<<(i-1))];
    }
  }
}
int lca(int u,int v){
  u = pos[u];
  v = pos[v];
  if(u > v)swap(u,v);
  int lg2 = 31 - __builtin_clz(v-u+1);
  int c1 = LCA[lg2][u];
  int c2 = LCA[lg2][v - (1<<lg2) + 1];
  if(dep[c1] < dep[c2])return c1;
  return c2;
}
int st[N],en[N],val[N];
void dfs(int u,int p = 0){
  st[u] = T++;
  val[T - 1] = u;
  for(auto it : G[u]){
    if(it == p)continue;
    dfs(it,u);
  }
  en[u] = T++;
  val[T - 1] = u;
}
int fr[N],bg[N],f[N],freq[2][N],ans[N];
ll ANS = 0;
void add(int pos){
  if(pos == -1)return;
  int v = val[pos];
  fr[v] ^= 1;
  if(fr[v] == 1){
    ANS += freq[bg[v]^1][f[v]];
    freq[bg[v]][f[v]] += 1;
  }
  else{
    ANS -= freq[bg[v]^1][f[v]];
    freq[bg[v]][f[v]] -= 1;
  }
}
int main(){
    fast;
    fill(dep, 0);
    fill(freq, 0);
    fill(fr, 0);
    int n;cin >> n;
    FOR(i,1,n)cin >> bg[i];
    vi com;
    FOR(i,1,n){
      cin >> f[i];
      com.pb(f[i]);
    }
    sort(all(com));
    com.erase(unique(all(com)),com.end());
    FOR(i,1,n){
      f[i] = lower_bound(all(com), f[i]) - com.begin();
    }
    FOR(i,1,n-1){
      int u,v;cin >> u >> v;
      G[u].pb(v);
      G[v].pb(u);
    }
    dfs(1);
    dfslca(1);
    LCApre();
    int q;cin >> q;
    FOR(i,0,q-1){
      int l,r;cin >> l >> r;
      if(st[l] > st[r])swap(l,r);
      int LCA = lca(l,r);
      if(LCA == l){
        Q[i].l = st[l];
        Q[i].r = st[r];
        Q[i].e = -1;
      }
      else{
        Q[i].l = en[l];
        Q[i].r = st[r];
        Q[i].e = st[LCA];
      }
      Q[i].i = i;
    }
    sort(Q,Q + q, cmp);
    int L = 1,R = 0;
    FOR(i,0,q-1){
      int x = Q[i].l,y = Q[i].r;
      while(L > x)add(--L);
      while(R < y)add(++R);
      while(L < x)add(L++);
      while(R > y)add(R--);
      add(Q[i].e);
      ans[Q[i].i] = ANS;
      add(Q[i].e);
    }
    FOR(i,0,q-1){
      cout << ans[i] << "\n";
    }
    return 0;
}


#include <bits/stdc++.h>

using namespace std;

typedef long long ll;
typedef vector<int> vi;
typedef pair<int,int> ii;

#define pb push_back
#define all(x) x.begin(),x.end()
#define sz(x) (int)x.size()
#define fill(a,x) memset(a,x,sizeof(a))
#define F first
#define S second
#define FOR(i,a,b) for(int i = a; i<=b; ++i)
#define NFOR(i,a,b) for(int i = a; i>=b; --i)
#define fast ios_base::sync_with_stdio(false),cin.tie(0),cout.tie(0)
const ll INF = 1e18;
const int mod = 1e9+7;
const int N = 2e5 + 10;
inline int add(int x,int y){
  x += y;
  if(x >= mod) x -= mod;
  return x;
}
inline int mul(int x,int y){
  x = (1LL * x * y) % mod;
  return x;
}
const int ROOT = 420;
struct node{
  int l,r,e,i;
}Q[N];

bool cmp(node x,node y){
  if(x.l/ROOT!=y.l/ROOT){
    return x.l/ROOT < y.l/ROOT;
  }
  return x.r<y.r;
}
int T = 1;
vector<int> G[N];
int dep[N];
int _n = 0;
int pos[N],LCA[20][2*N];
void dfslca(int v,int p = 0,int d = 0){
  pos[v] = _n;
  dep[v] = d;
  LCA[0][_n] = v;
  _n++;
  for(int it : G[v]){
    if(it != p){
      dfslca(it,v,d+1);
    }
  }
  if(p != 0){
    LCA[0][_n] = p;
    _n++;
  }
}
void LCApre(){
  for(int i = 1; i < 20 ; ++i){
    for(int j = 0 ; j  + (1<<(i-1)) < _n; ++j){
      if(dep[LCA[i-1][j]] < dep[LCA[i-1][j+(1<<(i-1))]])LCA[i][j] = LCA[i-1][j];
      else LCA[i][j] = LCA[i-1][j+(1<<(i-1))];
    }
  }
}
int lca(int u,int v){
  u = pos[u];
  v = pos[v];
  if(u > v)swap(u,v);
  int lg2 = 31 - __builtin_clz(v-u+1);
  int c1 = LCA[lg2][u];
  int c2 = LCA[lg2][v - (1<<lg2) + 1];
  if(dep[c1] < dep[c2])return c1;
  return c2;
}
int st[N],en[N],val[N];
void dfs(int u,int p = 0){
  st[u] = T++;
  val[T - 1] = u;
  for(auto it : G[u]){
    if(it == p)continue;
    dfs(it,u);
  }
  en[u] = T++;
  val[T - 1] = u;
}
int fr[N],bg[N],f[N],freq[2][N];
ll ans[N];
ll ANS = 0;
void add(int pos){
  if(pos == -1)return;
  int v = val[pos];
  fr[v] ^= 1;
  if(fr[v] == 1){
    ANS += freq[bg[v]^1][f[v]];
    freq[bg[v]][f[v]] += 1;
  }
  else{
    ANS -= freq[bg[v]^1][f[v]];
    freq[bg[v]][f[v]] -= 1;
  }
}
int main(){
    fast;
    fill(dep, 0);
    fill(freq, 0);
    fill(fr, 0);
    int n;cin >> n;
    FOR(i,1,n)cin >> bg[i];
    vi com;
    FOR(i,1,n){
      cin >> f[i];
      com.pb(f[i]);
    }
    sort(all(com));
    com.erase(unique(all(com)),com.end());
    FOR(i,1,n){
      f[i] = lower_bound(all(com), f[i]) - com.begin();
    }
    FOR(i,1,n-1){
      int u,v;cin >> u >> v;
      G[u].pb(v);
      G[v].pb(u);
    }
    dfs(1);
    dfslca(1);
    LCApre();
    int q;cin >> q;
    FOR(i,0,q-1){
      int l,r;cin >> l >> r;
      if(st[l] > st[r])swap(l,r);
      int p = lca(l,r);
      if(p == l){
        Q[i].l = st[l];
        Q[i].r = st[r];
        Q[i].e = -1;
      }
      else{
        Q[i].l = en[l];
        Q[i].r = st[r];
        Q[i].e = st[p];
      }
      Q[i].i = i;
    }
    sort(Q,Q + q, cmp);
    int L = 1,R = 0;
    FOR(i,0,q-1){
      int x = Q[i].l,y = Q[i].r;
      while(L > x)add(--L);
      while(R < y)add(++R);
      while(L < x)add(L++);
      while(R > y)add(R--);
      add(Q[i].e);
      ans[Q[i].i] = ANS;
      add(Q[i].e);
    }
    FOR(i,0,q-1){
      cout << ans[i] << "\n";
    }
    return 0;
}


#include <bits/stdc++.h>

using namespace std;

typedef long long ll;
typedef vector<int> vi;
typedef pair<int,int> ii;

#define pb push_back
#define all(x) x.begin(),x.end()
#define sz(x) (int)x.size()
#define fill(a,x) memset(a,x,sizeof(a))
#define F first
#define S second
#define FOR(i,a,b) for(int i = a; i<=b; ++i)
#define NFOR(i,a,b) for(int i = a; i>=b; --i)
#define fast ios_base::sync_with_stdio(false),cin.tie(0),cout.tie(0)
const ll INF = 1e18;
const int mod = 1e9+7;
const int N = 2e5 + 10;
inline int add(int x,int y){
  x += y;
  if(x >= mod) x -= mod;
  return x;
}
inline int mul(int x,int y){
  x = (1LL * x * y) % mod;
  return x;
}
const int ROOT = 420;
struct node{
  int l,r,e,i;
}Q[N];

bool cmp(node x,node y){
  if(x.l/ROOT!=y.l/ROOT){
    return x.l/ROOT < y.l/ROOT;
  }
  return x.r<y.r;
}
int T = 1;
vector<int> G[N];
int dep[N];
int _n = 0;
int pos[N],LCA[20][2*N];
void dfslca(int v,int p = 0,int d = 0){
  pos[v] = _n;
  dep[v] = d;
  LCA[0][_n] = v;
  _n++;
  for(int it : G[v]){
    if(it != p){
      dfslca(it,v,d+1);
    }
  }
  if(p != 0){
    LCA[0][_n] = p;
    _n++;
  }
}
void LCApre(){
  for(int i = 1; i < 20 ; ++i){
    for(int j = 0 ; j  + (1<<(i-1)) < _n; ++j){
      if(dep[LCA[i-1][j]] < dep[LCA[i-1][j+(1<<(i-1))]])LCA[i][j] = LCA[i-1][j];
      else LCA[i][j] = LCA[i-1][j+(1<<(i-1))];
    }
  }
}
int lca(int u,int v){
  u = pos[u];
  v = pos[v];
  if(u > v)swap(u,v);
  int lg2 = 31 - __builtin_clz(v-u+1);
  int c1 = LCA[lg2][u];
  int c2 = LCA[lg2][v - (1<<lg2) + 1];
  if(dep[c1] < dep[c2])return c1;
  return c2;
}
int st[N],en[N],val[N];
void dfs(int u,int p = 0){
  st[u] = T++;
  val[T - 1] = u;
  for(auto it : G[u]){
    if(it == p)continue;
    dfs(it,u);
  }
  en[u] = T++;
  val[T - 1] = u;
}
int fr[N],bg[N],f[N],freq[2][N],ans[N];
ll ANS = 0;
void add(int pos){
  int v = val[pos];
  fr[v] ^= 1;
  if(fr[v] == 1){
    ANS += freq[bg[v]^1][f[v]];
    freq[bg[v]][f[v]] += 1;
  }
  else{
    ANS -= freq[bg[v]^1][f[v]];
    freq[bg[v]][f[v]] -= 1;
  }
}
int main(){
    fast;
    fill(dep, 0);
    fill(freq, 0);
    fill(fr, 0);
    int n;cin >> n;
    FOR(i,1,n)cin >> bg[i];
    vi com;
    FOR(i,1,n){
      cin >> f[i];
      com.pb(f[i]);
    }
    sort(all(com));
    com.erase(unique(all(com)),com.end());
    FOR(i,1,n){
      f[i] = lower_bound(all(com), f[i]) - com.begin();
    }
    FOR(i,1,n-1){
      int u,v;cin >> u >> v;
      G[u].pb(v);
      G[v].pb(u);
    }
    dfs(1);
    dfslca(1);
    LCApre();
    int q;cin >> q;
    FOR(i,0,q-1){
      int l,r;cin >> l >> r;
      if(st[l] > st[r])swap(l,r);
      int LCA = lca(l,r);
      if(LCA == l){
        Q[i].l = st[l];
        Q[i].r = st[r];
        Q[i].e = -1;
      }
      else{
        Q[i].l = en[l];
        Q[i].r = st[r];
        Q[i].e = st[LCA];
      }
      Q[i].i = i;
    }
    sort(Q,Q + q, cmp);
    int L = 1,R = 0;
    FOR(i,0,q-1){
      int x = Q[i].l,y = Q[i].r;
      while(L > x)add(--L);
      while(R < y)add(++R);
      while(L < x)add(L++);
      while(R > y)add(R--);
      add(Q[i].e);
      ans[Q[i].i] = ANS;
      add(Q[i].e);
    }
    FOR(i,0,q-1){
      cout << ans[i] << "\n";
    }
    return 0;
}


#include <bits/stdc++.h>

using namespace std;

typedef long long ll;
typedef vector<int> vi;
typedef pair<int,int> ii;

#define pb push_back
#define all(x) x.begin(),x.end()
#define sz(x) (int)x.size()
#define fill(a,x) memset(a,x,sizeof(a))
#define F first
#define S second
#define FOR(i,a,b) for(int i = a; i<=b; ++i)
#define NFOR(i,a,b) for(int i = a; i>=b; --i)
#define fast ios_base::sync_with_stdio(false),cin.tie(0),cout.tie(0)
const ll INF = 1e18;
const int mod = 1e9+7;
const int N = 1e5 + 10;
inline int add(int x,int y){
  x += y;
  if(x >= mod) x -= mod;
  return x;
}
inline int mul(int x,int y){
  x = (1LL * x * y) % mod;
  return x;
}
const int ROOT = 350;
struct node{
  int l,r,e,i;
}Q[N];

bool cmp(node x,node y){
  if(x.l/ROOT!=y.l/ROOT){
    return x.l/ROOT < y.l/ROOT;
  }
  return x.r<y.r;
}
int T = 1;
vector<int> G[N];
int dep[N];
int _n = 0;
int pos[N],LCA[20][2*N];
void dfslca(int v,int p = 0,int d = 0){
  pos[v] = _n;
  dep[v] = d;
  LCA[0][_n] = v;
  _n++;
  for(int it : G[v]){
    if(it != p){
      dfslca(it,v,d+1);
    }
  }
  if(p != 0){
    LCA[0][_n] = p;
    _n++;
  }
}
void LCApre(){
  for(int i = 1; i < 20 ; ++i){
    for(int j = 0 ; j  + (1<<(i-1)) < _n; ++j){
      if(dep[LCA[i-1][j]] < dep[LCA[i-1][j+(1<<(i-1))]])LCA[i][j] = LCA[i-1][j];
      else LCA[i][j] = LCA[i-1][j+(1<<(i-1))];
    }
  }
}
int lca(int u,int v){
  u = pos[u];
  v = pos[v];
  if(u > v)swap(u,v);
  int lg2 = 31 - __builtin_clz(v-u+1);
  int c1 = LCA[lg2][u];
  int c2 = LCA[lg2][v - (1<<lg2) + 1];
  if(dep[c1] < dep[c2])return c1;
  return c2;
}
int st[N],en[N],val[N];
void dfs(int u,int p = 0){
  st[u] = T++;
  val[T - 1] = u;
  for(auto it : G[u]){
    if(it == p)continue;
    dfs(it,u);
  }
  en[u] = T++;
  val[T - 1] = u;
}
int fr[N],bg[N],f[N],freq[2][N],ans[N];
ll ANS = 0;
void add(int pos){
  int v = val[pos];
  fr[v] ^= 1;
  if(fr[v] == 1){
    ANS += freq[bg[v]^1][f[v]];
    freq[bg[v]][f[v]] += 1;
  }
  else{
    ANS -= freq[bg[v]^1][f[v]];
    freq[bg[v]][f[v]] -= 1;
  }
}
int main(){
    fast;
    fill(dep, 0);
    fill(freq, 0);
    fill(fr, 0);
    int n;cin >> n;
    FOR(i,1,n)cin >> bg[i];
    vi com;
    FOR(i,1,n){
      cin >> f[i];
      com.pb(f[i]);
    }
    sort(all(com));
    com.erase(unique(all(com)),com.end());
    FOR(i,1,n){
      f[i] = lower_bound(all(com), f[i]) - com.begin();
    }
    FOR(i,1,n-1){
      int u,v;cin >> u >> v;
      G[u].pb(v);
      G[v].pb(u);
    }
    dfs(1);
    dfslca(1);
    LCApre();
    int q;cin >> q;
    FOR(i,0,q-1){
      int l,r;cin >> l >> r;
      if(st[l] > st[r])swap(l,r);
      int LCA = lca(l,r);
      if(LCA == l){
        Q[i].l = st[l];
        Q[i].r = st[r];
        Q[i].e = -1;
      }
      else{
        Q[i].l = en[l];
        Q[i].r = st[r];
        Q[i].e = st[LCA];
      }
      Q[i].i = i;
    }
    sort(Q,Q + q, cmp);
    int L = 1,R = 0;
    FOR(i,0,q-1){
      int x = Q[i].l,y = Q[i].r;
      while(L > x)add(--L);
      while(R < y)add(++R);
      while(L < x)add(L++);
      while(R > y)add(R--);
      add(Q[i].e);
      ans[Q[i].i] = ANS;
      add(Q[i].e);
    }
    FOR(i,0,q-1){
      cout << ans[i] << "\n";
    }
    return 0;
}


#pragma GCC optimize("Ofast,no-stack-protector,unroll-loops,fast-math,O3")
#pragma GCC target("sse,sse2,sse3,ssse3,sse4,popcnt,abm,mmx,avx,tune=native")
#include <bits/stdc++.h>
#define pb push_back
#define ll long long
#define mp make_pair
#define si short int
#define speed ios_base::sync_with_stdio(0),cin.tie(0),cout.tie(0)
#define pill pair<ll,ll>
#define f first
#define s second
#define pilc pair<ll,char>
#define all(a) (a).begin(),(a).end()
#define rep(s,e,step) for(int i = (s); i < (e) ; i += step)
#define vrep(s,e,step) for(int j = (s); j < (e) ; j += step)
#define ex exit(0)
#define sz(a) (a).size()
#define triple pair<pill, ll>
#define pinode pair<node*, node*>
#define quadra pair<pill, pill>
using namespace std;

/*
 tips :
 Sqrt opt
 Binary search
 Try to find the easiest solution
 Recursiya
 FUCK YOU pishi kod akuratnee daun yobani
 sdohni v adu nahui blyat' y ub'uy tebya
 esli ti blyad' budesh pisat' kod gryaznim
 to ya tebya v rot viebu
*/

const ll N = 2e5 + 10;
const ll M = 3e8 + 1;
const ll big = 1e18;
const ll shift = 1000;
const ll hsh2 = 1964325029 ;
const long long mod = 998244353;
const long double EPS = 1e-14;
const ll block = 700;
ll n;
ll f[N];
void szhim() {
	vector<ll> d;
	for(int i = 1; i <= n; i++)
		d.pb(f[i]);
	sort(all(d));
	d.erase(unique(all(d)), d.end());
	for(int i = 1; i <= n; i++)
		f[i] = lower_bound(all(d), f[i]) - d.begin();
}

vector<ll> g[N];
ll bp[N][20];
bool boy[N];
ll tin[N], tout[N], cnt[2][N];
ll eul[N], L[N], R[N];
ll answ = 0, ans[N];
bool was[N];
ll q;

void dfs(ll v, ll p) {
	tin[v] = ++tout[0];
	eul[tin[v]] = v;
	bp[v][0] = p;
	for(int i = 1; i < 20; i++)
		bp[v][i] = bp[bp[v][i - 1]][i - 1];
	for(auto u : g[v])
		if(u != p)
			dfs(u, v);
	tout[v] = ++tout[0];
	eul[tout[v]] = v;
}
bool upper(ll a, ll b) {
	return (tin[a] <= tin[b] && tout[b] <= tout[a]);
}

ll LCA(ll a, ll b) {
 	if(upper(a, b))
 		return 0;
	if(upper(b, a))
		return 0;
	for(int i = 19; i >= 0; i--)
		if(!upper(bp[a][i], b))
			a = bp[a][i];
	return bp[a][0];
}

void upd(ll a) {
 	if(!was[a]) {
 		answ += cnt[!boy[a]][f[a]];
 		cnt[boy[a]][f[a]]++;
 	}
 	else {
 	 	cnt[boy[a]][f[a]]--;
 	 	answ -= cnt[!boy[a]][f[a]];
 	}
	was[a] ^= 1;
}

vector<ll> Q;

bool comp(ll a, ll b) {
 	if(L[a] != L[b])
 		return L[a] < L[b];
	return R[a] < R[b];
}

int main() {
	speed;
	cin >> n;
	for(int i = 1; i <= n; i++)
		cin >> boy[i];
	for(int i = 1; i <= n; i++)
		cin >> f[i];
	szhim();
	for(int i = 1, a, b; i < n; i++) {
		cin >> a >> b;
		g[a].pb(b), g[b].pb(a);
	}
	dfs(1, 0);
	cin >> q;
	for(int i = 1; i <= q; i++) {
		Q.pb(i);
		cin >> L[i] >> R[i];
		if(upper(L[i], R[i]) || upper(R[i], L[i]))
			L[i] = tin[L[i]], R[i] = tin[R[i]];
		else {
			if(tin[L[i]] > tin[R[i]])
				swap(L[i], R[i]);
			L[i] = tout[L[i]];
			R[i] = tin[R[i]];
		}
		if(L[i] > R[i])
			swap(L[i], R[i]);
	}
	sort(all(Q), comp);
	ll l = 1, r = 0;
	for(auto u : Q) {
		while(l > L[u]) upd(eul[--l]);
		while(r < R[u]) upd(eul[++r]);
		while(l < L[u]) upd(eul[l++]);
		while(r > R[u]) upd(eul[r--]);
		ll z = LCA(eul[l], eul[r]);
		ans[u] = answ + (z ? 1 : 0) * cnt[!boy[z]][f[z]];
    }
    for(int i = 1; i <= q; i++)
    	cout << ans[i] << '\n';
}

/*
7
1 0 0 1 0 1 0
9 2 9 2 2 9 9
2 6
1 2
4 2
6 5
3 6
7 4
2
7 1
3 1

*/


#pragma GCC optimize("Ofast,no-stack-protector,unroll-loops,fast-math,O3")
#pragma GCC target("sse,sse2,sse3,ssse3,sse4,popcnt,abm,mmx,avx,tune=native")
#include <bits/stdc++.h>
#define pb push_back
#define ll long long
#define mp make_pair
#define si short int
#define speed ios_base::sync_with_stdio(0),cin.tie(0),cout.tie(0)
#define pill pair<ll,ll>
#define f first
#define s second
#define pilc pair<ll,char>
#define all(a) (a).begin(),(a).end()
#define rep(s,e,step) for(int i = (s); i < (e) ; i += step)
#define vrep(s,e,step) for(int j = (s); j < (e) ; j += step)
#define ex exit(0)
#define sz(a) (a).size()
#define triple pair<pill, ll>
#define pinode pair<node*, node*>
#define quadra pair<pill, pill>
using namespace std;

/*
 tips :
 Sqrt opt
 Binary search
 Try to find the easiest solution
 Recursiya
 FUCK YOU pishi kod akuratnee daun yobani
 sdohni v adu nahui blyat' y ub'uy tebya
 esli ti blyad' budesh pisat' kod gryaznim
 to ya tebya v rot viebu
*/

const ll N = 2e5 + 10;
const ll M = 3e8 + 1;
const ll big = 1e18;
const ll shift = 1000;
const ll hsh2 = 1964325029 ;
const long long mod = 998244353;
const long double EPS = 1e-14;
const ll block = 700;
ll n;
ll f[N];
void szhim() {
	vector<ll> d;
	for(int i = 1; i <= n; i++)
		d.pb(f[i]);
	sort(all(d));
	d.erase(unique(all(d)), d.end());
	for(int i = 1; i <= n; i++)
		f[i] = lower_bound(all(d), f[i]) - d.begin();
}

vector<ll> g[N];
ll bp[N][20];
bool boy[N];
ll tin[N], tout[N], cnt[2][N];
ll eul[N], L[N], R[N];
ll answ = 0, ans[N];
bool was[N];
ll q;

void dfs(ll v, ll p) {
	tin[v] = ++tout[0];
	eul[tin[v]] = v;
	bp[v][0] = p;
	for(int i = 1; i < 20; i++)
		bp[v][i] = bp[bp[v][i - 1]][i - 1];
	for(auto u : g[v])
		if(u != p)
			dfs(u, v);
	tout[v] = ++tout[0];
	eul[tout[v]] = v;
}
bool upper(ll a, ll b) {
	return (tin[a] <= tin[b] && tout[b] <= tout[a]);
}

ll LCA(ll a, ll b) {
 	if(upper(a, b))
 		return 0;
	if(upper(b, a))
		return 0;
	for(int i = 19; i >= 0; i--)
		if(!upper(bp[a][i], b))
			a = bp[a][i];
	return bp[a][0];
}

void upd(ll a) {
 	if(!was[a]) {
 		answ += cnt[!boy[a]][f[a]];
 		cnt[boy[a]][f[a]]++;
 	}
 	else {
 	 	cnt[boy[a]][f[a]]--;
 	 	answ -= cnt[!boy[a]][f[a]];
 	}
	was[a] ^= 1;
}

vector<ll> Q;

bool comp(ll a, ll b) {
 	if(L[a] / block != L[b] / block)
 		return L[a] < L[b];
	return R[a] < R[b];
}

int main() {
	speed;
	cin >> n;
	for(int i = 1; i <= n; i++)
		cin >> boy[i];
	for(int i = 1; i <= n; i++)
		cin >> f[i];
	szhim();
	for(int i = 1, a, b; i < n; i++) {
		cin >> a >> b;
		g[a].pb(b), g[b].pb(a);
	}
	dfs(1, 0);
	cin >> q;
	for(int i = 1; i <= q; i++) {
		Q.pb(i);
		cin >> L[i] >> R[i];
		if(upper(L[i], R[i]) || upper(R[i], L[i]))
			L[i] = tin[L[i]], R[i] = tin[R[i]];
		else {
			if(tin[L[i]] > tin[R[i]])
				swap(L[i], R[i]);
			L[i] = tout[L[i]];
			R[i] = tin[R[i]];
		}
		if(L[i] > R[i])
			swap(L[i], R[i]);
	}
	sort(all(Q), comp);
	ll l = 1, r = 0;
	for(auto u : Q) {
		while(l > L[u]) upd(eul[--l]);
		while(r < R[u]) upd(eul[++r]);
		while(l < L[u]) upd(eul[l++]);
		while(r > R[u]) upd(eul[r--]);
		ll z = LCA(eul[l], eul[r]);
		ans[u] = answ + (z ? 1 : 0) * cnt[!boy[z]][f[z]];
    }
    for(int i = 1; i <= q; i++)
    	cout << ans[i] << '\n';
}

/*
7
1 0 0 1 0 1 0
9 2 9 2 2 9 9
2 6
1 2
4 2
6 5
3 6
7 4
2
7 1
3 1

*/


#include <bits/stdc++.h>
#define pb push_back
#define ll long long
#define mp make_pair
#define si short int
#define speed ios_base::sync_with_stdio(0),cin.tie(0),cout.tie(0)
#define pill pair<ll,ll>
#define f first
#define s second
#define pilc pair<ll,char>
#define all(a) (a).begin(),(a).end()
#define rep(s,e,step) for(int i = (s); i < (e) ; i += step)
#define vrep(s,e,step) for(int j = (s); j < (e) ; j += step)
#define ex exit(0)
#define sz(a) (a).size()
#define triple pair<pill, ll>
#define pinode pair<node*, node*>
#define quadra pair<pill, pill>
using namespace std;

/*
 tips :
 Sqrt opt
 Binary search
 Try to find the easiest solution
 Recursiya
 FUCK YOU pishi kod akuratnee daun yobani
 sdohni v adu nahui blyat' y ub'uy tebya
 esli ti blyad' budesh pisat' kod gryaznim
 to ya tebya v rot viebu
*/

const ll N = 2e5 + 10;
const ll M = 3e8 + 1;
const ll big = 1e18;
const ll shift = 1000;
const ll hsh2 = 1964325029 ;
const long long mod = 998244353;
const long double EPS = 1e-14;
const ll block = 700;
ll n;
ll f[N];
void szhim() {
	vector<ll> d;
	for(int i = 1; i <= n; i++)
		d.pb(f[i]);
	sort(all(d));
	d.erase(unique(all(d)), d.end());
	for(int i = 1; i <= n; i++)
		f[i] = lower_bound(all(d), f[i]) - d.begin();
}

vector<ll> g[N];
ll bp[N][20];
bool boy[N];
ll tin[N], tout[N], cnt[2][N];
ll eul[N], L[N], R[N];
ll answ = 0, ans[N];
bool was[N];
ll q;

void dfs(ll v, ll p) {
	tin[v] = ++tout[0];
	eul[tin[v]] = v;
	bp[v][0] = p;
	for(int i = 1; i < 20; i++)
		bp[v][i] = bp[bp[v][i - 1]][i - 1];
	for(auto u : g[v])
		if(u != p)
			dfs(u, v);
	tout[v] = ++tout[0];
	eul[tout[v]] = v;
}
bool upper(ll a, ll b) {
	return (tin[a] <= tin[b] && tout[b] <= tout[a]);
}

ll LCA(ll a, ll b) {
 	if(upper(a, b))
 		return 0;
	if(upper(b, a))
		return 0;
	for(int i = 19; i >= 0; i--)
		if(!upper(bp[a][i], b))
			a = bp[a][i];
	return bp[a][0];
}

void upd(ll a) {
 	if(!was[a]) {
 		answ += cnt[!boy[a]][f[a]];
 		cnt[boy[a]][f[a]]++;
 	}
 	else {
 	 	cnt[boy[a]][f[a]]--;
 	 	answ -= cnt[!boy[a]][f[a]];
 	}
	was[a] ^= 1;
}

vector<ll> Q;

bool comp(ll a, ll b) {
 	if(L[a] != L[b])
 		return L[a] < L[b];
	return R[a] < R[b];
}

int main() {
	speed;
	cin >> n;
	for(int i = 1; i <= n; i++)
		cin >> boy[i];
	for(int i = 1; i <= n; i++)
		cin >> f[i];
	szhim();
	for(int i = 1, a, b; i < n; i++) {
		cin >> a >> b;
		g[a].pb(b), g[b].pb(a);
	}
	dfs(1, 0);
	cin >> q;
	for(int i = 1; i <= q; i++) {
		Q.pb(i);
		cin >> L[i] >> R[i];
		if(upper(L[i], R[i]) || upper(R[i], L[i]))
			L[i] = tin[L[i]], R[i] = tin[R[i]];
		else {
			if(tin[L[i]] > tin[R[i]])
				swap(L[i], R[i]);
			L[i] = tout[L[i]];
			R[i] = tin[R[i]];
		}
		if(L[i] > R[i])
			swap(L[i], R[i]);
	}
	sort(all(Q), comp);
	ll l = 1, r = 0;
	for(auto u : Q) {
		while(l > L[u]) upd(eul[--l]);
		while(r < R[u]) upd(eul[++r]);
		while(l < L[u]) upd(eul[l++]);
		while(r > R[u]) upd(eul[r--]);
		ll z = LCA(eul[l], eul[r]);
		ans[u] = answ + (z ? 1 : 0) * cnt[!boy[z]][f[z]];
    }
    for(int i = 1; i <= q; i++)
    	cout << ans[i] << '\n';
}

/*
7
1 0 0 1 0 1 0
9 2 9 2 2 9 9
2 6
1 2
4 2
6 5
3 6
7 4
2
7 1
3 1

*/


#include <bits/stdc++.h>
#define pb push_back
#define ll long long
#define mp make_pair
#define si short int
#define speed ios_base::sync_with_stdio(0),cin.tie(0),cout.tie(0)
#define pill pair<ll,ll>
#define f first
#define s second
#define pilc pair<ll,char>
#define all(a) (a).begin(),(a).end()
#define rep(s,e,step) for(int i = (s); i < (e) ; i += step)
#define vrep(s,e,step) for(int j = (s); j < (e) ; j += step)
#define ex exit(0)
#define sz(a) (a).size()
#define triple pair<pill, ll>
#define pinode pair<node*, node*>
#define quadra pair<pill, pill>
using namespace std;

/*
 tips :
 Sqrt opt
 Binary search
 Try to find the easiest solution
 Recursiya
 FUCK YOU pishi kod akuratnee daun yobani
 sdohni v adu nahui blyat' y ub'uy tebya
 esli ti blyad' budesh pisat' kod gryaznim
 to ya tebya v rot viebu
*/

const ll N = 1e5 + 10;
const ll M = 3e8 + 1;
const ll big = 1e18;
const ll shift = 1000;
const ll hsh2 = 1964325029 ;
const long long mod = 998244353;
const long double EPS = 1e-14;
const ll block = 700;
ll n;
ll f[N];
void szhim() {
	vector<ll> d;
	for(int i = 1; i <= n; i++)
		d.pb(f[i]);
	sort(all(d));
	d.erase(unique(all(d)), d.end());
	for(int i = 1; i <= n; i++)
		f[i] = lower_bound(all(d), f[i]) - d.begin();
}

vector<ll> g[N];
ll bp[N][20];
bool boy[N];
ll tin[N], tout[N], cnt[2][N];
ll eul[N], L[N], R[N];
ll answ = 0, ans[N];
bool was[N];
ll q;

void dfs(ll v, ll p) {
	tin[v] = ++tout[0];
	eul[tin[v]] = v;
	bp[v][0] = p;
	for(int i = 1; i < 20; i++)
		bp[v][i] = bp[bp[v][i - 1]][i - 1];
	for(auto u : g[v])
		if(u != p)
			dfs(u, v);
	tout[v] = ++tout[0];
	eul[tout[v]] = v;
}
bool upper(ll a, ll b) {
	return (tin[a] <= tin[b] && tout[b] <= tout[a]);
}

ll LCA(ll a, ll b) {
 	if(upper(a, b))
 		return 0;
	if(upper(b, a))
		return 0;
	for(int i = 19; i >= 0; i--)
		if(!upper(bp[a][i], b))
			a = bp[a][i];
	return bp[a][0];
}

void upd(ll a) {
 	if(!was[a]) {
 		answ += cnt[!boy[a]][f[a]];
 		cnt[boy[a]][f[a]]++;
 	}
 	else {
 	 	cnt[boy[a]][f[a]]--;
 	 	answ -= cnt[!boy[a]][f[a]];
 	}
	was[a] ^= 1;
}

vector<ll> Q;

bool comp(ll a, ll b) {
 	if(L[a] != L[b])
 		return L[a] < L[b];
	return R[a] < R[b];
}

int main() {
	speed;
	cin >> n;
	for(int i = 1; i <= n; i++)
		cin >> boy[i];
	for(int i = 1; i <= n; i++)
		cin >> f[i];
	szhim();
	for(int i = 1, a, b; i < n; i++) {
		cin >> a >> b;
		g[a].pb(b), g[b].pb(a);
	}
	dfs(1, 0);
	cin >> q;
	for(int i = 1; i <= q; i++) {
		Q.pb(i);
		cin >> L[i] >> R[i];
		if(upper(L[i], R[i]) || upper(R[i], L[i]))
			L[i] = tin[L[i]], R[i] = tin[R[i]];
		else {
			if(tin[L[i]] > tin[R[i]])
				swap(L[i], R[i]);
			L[i] = tout[L[i]];
			R[i] = tin[R[i]];
		}
		if(L[i] > R[i])
			swap(L[i], R[i]);
	}
	sort(all(Q), comp);
	ll l = 1, r = 0;
	for(auto u : Q) {
		while(l > L[u]) upd(eul[--l]);
		while(r < R[u]) upd(eul[++r]);
		while(l < L[u]) upd(eul[l++]);
		while(r > R[u]) upd(eul[r--]);
		ll z = LCA(eul[l], eul[r]);
		ans[u] = answ + (z ? 1 : 0) * cnt[!boy[z]][f[z]];
    }
    for(int i = 1; i <= q; i++)
    	cout << ans[i] << '\n';
}

/*
7
1 0 0 1 0 1 0
9 2 9 2 2 9 9
2 6
1 2
4 2
6 5
3 6
7 4
2
7 1
3 1

*/


//TooMuchMath
#include<bits/stdc++.h>

using namespace std;

typedef pair<int,int>   II;
typedef vector< II >      VII;
typedef vector<int>     VI;
typedef vector< VI > 	VVI;
typedef long long int 	LL;

#define PB push_back
#define MP make_pair
#define F first
#define S second
#define SZ(a) (int)(a.size())
#define ALL(a) a.begin(),a.end()
#define SET(a,b) memset(a,b,sizeof(a))
#define FOR(i, a, b) for (int i = (a); i < (b); ++i)
#define REP(i, n) FOR(i, 0, n)

#define si(n) scanf("%d",&n)
#define dout(n) printf("%d\n",n)
#define sll(n) scanf("%lld",&n)
#define lldout(n) printf("%lld\n",n)
#define fast_io ios_base::sync_with_stdio(false);cin.tie(NULL)

#define TRACE

#ifdef TRACE
#define trace(...) __f(#__VA_ARGS__, __VA_ARGS__)
template <typename Arg1>
void __f(const char* name, Arg1&& arg1){
	cerr << name << " : " << arg1 << std::endl;
}
template <typename Arg1, typename... Args>
void __f(const char* names, Arg1&& arg1, Args&&... args){
	const char* comma = strchr(names + 1, ',');cerr.write(names, comma - names) << " : " << arg1<<" | ";__f(comma+1, args...);
}
#else
#define trace(...)
#endif

//FILE *fin = freopen("in","r",stdin);
//FILE *fout = freopen("out","w",stdout);

const int N = int(2e5)+10;
const int LOGN = 20;
const int BLOCK = 500;
VI g[N];
int st[N],en[N],level[N],DP[LOGN][N],Time;
int who[N],f[N], ID[N];
map<int,int> mp;
struct query{
  int l, r, lc, id, bl;
}Q[N];
void dfs(int x, int p){
  st[x] = ++Time;
  ID[Time] = x;
  DP[0][x] = p;
  for(auto y : g[x]){
    if(y == p)continue;
    level[y] = level[x] + 1;
    dfs(y, x);
  }
  en[x] = ++Time;
  ID[Time] = x;
}
int lca(int a,int b){
  if(level[a] > level[b])swap(a,b);
  int d = level[b] - level[a];
  for(int i=0;i<LOGN;i++)
    if((1<<i) & d)
      b = DP[i][b];
  if(a == b)return a;
  for(int i=LOGN-1;i>=0;i--)
    if(DP[i][a] != DP[i][b])
      a = DP[i][a], b = DP[i][b];
  return DP[0][a];
}
int vis[N], sum[N][2];
LL cans, ans[N];
void go(int x){
  int c = f[x], b = who[x];
  if(vis[x]){
    cans -= sum[c][1 - b];
    sum[c][b]--;
  }
  else {
    cans += sum[c][1 - b];
    sum[c][b]++;
  }
  vis[x] ^= 1;
}
int main()
{
  int n;si(n);
  for(int i=1;i<=n;i++)si(who[i]);
  for(int i=1;i<=n;i++)si(f[i]),mp[f[i]];
  int len = 0;
  for(auto &it:mp)it.S = ++len;
  for(int i=1;i<=n;i++)f[i] = mp[f[i]];
  for(int i=1;i<n;i++){
    int a,b;
    si(a);si(b);
    g[a].PB(b);
    g[b].PB(a);
  }
  dfs(1,1);
  for(int i=1;i<LOGN;i++)
    for(int j=1;j<=n;j++)
      DP[i][j] = DP[i-1][DP[i-1][j]];
  int q;si(q);
  for(int i=1;i<=q;i++){
    int a,b;
    si(a);si(b);
    if(st[a] > st[b])swap(a,b);
    Q[i].lc = lca(a, b);
    Q[i].id = i;
    if(Q[i].lc == a){
      //case - 1
      Q[i].l = st[a];
      Q[i].r = st[b];
      Q[i].lc = -1;
    }
    else {
      //case - 2
      Q[i].l = en[a];
      Q[i].r = st[b];
    }
    Q[i].bl = Q[i].l / BLOCK;
  }
  sort(Q+1, Q+1+q, [](query a, query b){return (a.bl != b.bl) ? (a.bl < b.bl) : (a.r < b.r);});
  int L = 1, R = 0;
  for(int i=1;i<=q;i++){
    int l = Q[i].l, r = Q[i].r;
    while(R < r)go(ID[++R]);
    while(L > l)go(ID[--L]);
    while(R > r)go(ID[R--]);
    while(L < l)go(ID[L++]);
    if(Q[i].lc != -1){
      go(Q[i].lc);
      ans[Q[i].id] = cans;
      go(Q[i].lc);
    }
    else {
      ans[Q[i].id] = cans;
    }
  }
  for(int i=1;i<=q;i++)
    lldout(ans[i]);

	return 0;
}


//TooMuchMath
#include<bits/stdc++.h>

using namespace std;

typedef pair<int,int>   II;
typedef vector< II >      VII;
typedef vector<int>     VI;
typedef vector< VI > 	VVI;
typedef long long int 	LL;

#define PB push_back
#define MP make_pair
#define F first
#define S second
#define SZ(a) (int)(a.size())
#define ALL(a) a.begin(),a.end()
#define SET(a,b) memset(a,b,sizeof(a))
#define FOR(i, a, b) for (int i = (a); i < (b); ++i)
#define REP(i, n) FOR(i, 0, n)

#define si(n) scanf("%d",&n)
#define dout(n) printf("%d\n",n)
#define sll(n) scanf("%lld",&n)
#define lldout(n) printf("%lld\n",n)
#define fast_io ios_base::sync_with_stdio(false);cin.tie(NULL)

#define TRACE

#ifdef TRACE
#define trace(...) __f(#__VA_ARGS__, __VA_ARGS__)
template <typename Arg1>
void __f(const char* name, Arg1&& arg1){
	cerr << name << " : " << arg1 << std::endl;
}
template <typename Arg1, typename... Args>
void __f(const char* names, Arg1&& arg1, Args&&... args){
	const char* comma = strchr(names + 1, ',');cerr.write(names, comma - names) << " : " << arg1<<" | ";__f(comma+1, args...);
}
#else
#define trace(...)
#endif

//FILE *fin = freopen("in","r",stdin);
//FILE *fout = freopen("out","w",stdout);

const int N = int(2e5)+10;
const int LOGN = 20;
const int BLOCK = 500;
VI g[N];
int st[N],en[N],level[N],DP[LOGN][N],Time;
int who[N],f[N], ID[N];
map<int,int> mp;
struct query{
  int l, r, lc, id, bl;
}Q[N];
void dfs(int x, int p){
  st[x] = ++Time;
  ID[Time] = x;
  DP[0][x] = p;
  for(auto y : g[x]){
    if(y == p)continue;
    level[y] = level[x] + 1;
    dfs(y, x);
  }
  en[x] = ++Time;
  ID[Time] = x;
}
int lca(int a,int b){
  if(level[a] > level[b])swap(a,b);
  int d = level[b] - level[a];
  for(int i=0;i<d;i++)
    if((1<<i) & d)
      b = DP[i][b];
  if(a == b)return a;
  for(int i=LOGN-1;i>=0;i--)
    if(DP[i][a] != DP[i][b])
      a = DP[i][a], b = DP[i][b];
  return DP[0][a];
}
int vis[N], sum[N][2];
LL cans, ans[N];
void go(int x){
  int c = f[x], b = who[x];
  if(vis[x]){
    cans -= sum[c][1 - b];
    sum[c][b]--;
  }
  else {
    cans += sum[c][1 - b];
    sum[c][b]++;
  }
  vis[x] ^= 1;
}
int main()
{
  int n;si(n);
  for(int i=1;i<=n;i++)si(who[i]);
  for(int i=1;i<=n;i++)si(f[i]),mp[f[i]];
  int len = 0;
  for(auto &it:mp)it.S = ++len;
  for(int i=1;i<=n;i++)f[i] = mp[f[i]];
  for(int i=1;i<n;i++){
    int a,b;
    si(a);si(b);
    g[a].PB(b);
    g[b].PB(a);
  }
  dfs(1,1);
  for(int i=1;i<LOGN;i++)
    for(int j=1;j<=n;j++)
      DP[i][j] = DP[i-1][DP[i-1][j]];
  int q;si(q);
  for(int i=1;i<=q;i++){
    int a,b;
    si(a);si(b);
    if(st[a] > st[b])swap(a,b);
    Q[i].lc = lca(a, b);
    Q[i].id = i;
    if(Q[i].lc == a){
      //case - 1
      Q[i].l = st[a];
      Q[i].r = st[b];
      Q[i].lc = -1;
    }
    else {
      //case - 2
      Q[i].l = en[a];
      Q[i].r = st[b];
    }
    Q[i].bl = Q[i].l / BLOCK;
  }
  sort(Q+1, Q+1+q, [](query a, query b){return (a.bl != b.bl) ? (a.bl < b.bl) : (a.r < b.r);});
  int L = 1, R = 0;
  for(int i=1;i<=q;i++){
    int l = Q[i].l, r = Q[i].r;
    while(R < r)go(ID[++R]);
    while(L > l)go(ID[--L]);
    while(R > r)go(ID[R--]);
    while(L < l)go(ID[L++]);
    if(Q[i].lc != -1){
      go(Q[i].lc);
      ans[Q[i].id] = cans;
      go(Q[i].lc);
    }
    else {
      ans[Q[i].id] = cans;
    }
  }
  for(int i=1;i<=q;i++)
    lldout(ans[i]);

	return 0;
}


//TooMuchMath
#include<bits/stdc++.h>

using namespace std;

typedef pair<int,int>   II;
typedef vector< II >      VII;
typedef vector<int>     VI;
typedef vector< VI > 	VVI;
typedef long long int 	LL;

#define PB push_back
#define MP make_pair
#define F first
#define S second
#define SZ(a) (int)(a.size())
#define ALL(a) a.begin(),a.end()
#define SET(a,b) memset(a,b,sizeof(a))
#define FOR(i, a, b) for (int i = (a); i < (b); ++i)
#define REP(i, n) FOR(i, 0, n)

#define si(n) scanf("%d",&n)
#define dout(n) printf("%d\n",n)
#define sll(n) scanf("%lld",&n)
#define lldout(n) printf("%lld\n",n)
#define fast_io ios_base::sync_with_stdio(false);cin.tie(NULL)

#define TRACE

#ifdef TRACE
#define trace(...) __f(#__VA_ARGS__, __VA_ARGS__)
template <typename Arg1>
void __f(const char* name, Arg1&& arg1){
	cerr << name << " : " << arg1 << std::endl;
}
template <typename Arg1, typename... Args>
void __f(const char* names, Arg1&& arg1, Args&&... args){
	const char* comma = strchr(names + 1, ',');cerr.write(names, comma - names) << " : " << arg1<<" | ";__f(comma+1, args...);
}
#else
#define trace(...)
#endif

//FILE *fin = freopen("in","r",stdin);
//FILE *fout = freopen("out","w",stdout);

const int N = int(2e5)+10;
const int LOGN = 20;
const int BLOCK = 500;
VI g[N];
int st[N],en[N],level[N],DP[LOGN][N],Time;
int who[N],f[N], ID[N];
map<int,int> mp;
struct query{
  int l, r, lc, id, bl;
}Q[N];
void dfs(int x, int p){
  st[x] = ++Time;
  ID[Time] = x;
  DP[0][x] = p;
  for(auto y : g[x]){
    if(y == p)continue;
    level[y] = level[x] + 1;
    dfs(y, x);
  }
  en[x] = ++Time;
  ID[Time] = x;
}
int lca(int a,int b){
  if(level[a] > level[b])swap(a,b);
  int d = level[b] - level[a];
  for(int i=0;i<d;i++)
    if((1<<i) & d)
      b = DP[i][b];
  if(a == b)return a;
  for(int i=LOGN-1;i>=0;i--)
    if(DP[i][a] != DP[i][b])
      a = DP[i][a], b = DP[i][b];
  return DP[0][a];
}
int vis[N], sum[N][2];
LL cans, ans[N];
void go(int x){
  int c = f[x], b = who[x];
  if(vis[x]){
    cans -= sum[c][1 - b];
    sum[c][b]--;
  }
  else {
    cans += sum[c][1 - b];
    sum[c][b]++;
  }
  vis[x] ^= 1;
}
int main()
{
  int n;si(n);
  for(int i=1;i<=n;i++)si(who[i]);
  for(int i=1;i<=n;i++)si(f[i]),mp[f[i]];
  int len = 0;
  for(auto &it:mp)it.S = ++len;
  for(int i=1;i<=n;i++)f[i] = mp[f[i]];
  for(int i=1;i<n;i++){
    int a,b;
    si(a);si(b);
    g[a].PB(b);
    g[b].PB(a);
  }
  dfs(1,1);
  for(int i=1;i<LOGN;i++)
    for(int j=1;j<=n;j++)
      DP[i][j] = DP[i-1][DP[i-1][j]];
  int q;si(q);
  for(int i=1;i<=q;i++){
    int a,b;
    si(a);si(b);
    if(level[a] > level[b])swap(a,b);
    Q[i].lc = lca(a, b);
    Q[i].id = i;
    if(Q[i].lc == a){
      //case - 1
      Q[i].l = st[a];
      Q[i].r = st[b];
      Q[i].lc = -1;
    }
    else {
      //case - 2
      Q[i].l = en[a];
      Q[i].r = st[b];
    }
    Q[i].bl = Q[i].l / BLOCK;
  }
  sort(Q+1, Q+1+q, [](query a, query b){return (a.bl != b.bl) ? (a.bl < b.bl) : (a.r < b.r);});
  int L = 1, R = 0;
  for(int i=1;i<=q;i++){
    int l = Q[i].l, r = Q[i].r;
    while(R < r)go(ID[++R]);
    while(L > l)go(ID[--L]);
    while(R > r)go(ID[R--]);
    while(L < l)go(ID[L++]);
    if(Q[i].lc != -1){
      go(Q[i].lc);
      ans[Q[i].id] = cans;
      go(Q[i].lc);
    }
    else {
      ans[Q[i].id] = cans;
    }
  }
  for(int i=1;i<=q;i++)
    lldout(ans[i]);

	return 0;
}


/**
 *    author:  tourist
 *    created: 03.09.2017 13:50:22
**/

// HackerRank University CodeSprint, problem "Counting On a Tree", modified

#include <bits/stdc++.h>

using namespace std;

struct Query {
  int a;
  int b;
  int coeff;
  int id;
};

int BLOCK;

inline bool cmp(Query &x, Query &y) {
  int X = x.a / BLOCK;
  int Y = y.a / BLOCK;
  if (X != Y) {
    return X < Y;
  }
  return x.b < y.b;
}

const int N = 100010;
const int LOG = 20;

vector <int> order;
int entry[N], brexit[N];
int pv[N];
int pr[N][LOG];
Query qs[16 * N];
long long result[N];
int in_a[N], in_b[N];
int label[N];
vector <int> g[N];
int depth[N];
pair <int, int> ev[N];
int type[N];

void dfs(int v, int pr) {
  entry[v] = order.size();
  order.push_back(v);
  int sz = g[v].size();
  for (int j = 0; j < sz; j++) {
    int u = g[v][j];
    if (u != pr) {
      pv[u] = v;
      depth[u] = depth[v] + 1;
      dfs(u, v);
    }
  }
  brexit[v] = order.size();
  order.push_back(~v);
}

inline bool anc(int x, int y) {
  return (entry[x] <= entry[y] && brexit[y] <= brexit[x]);
}

inline int lca(int x, int y) {
  if (anc(x, y)) {
    return x;
  }
  for (int j = LOG - 1; j >= 0; j--) {
    if (!anc(pr[x][j], y)) {
      x = pr[x][j];
    }
  }
  return pr[x][0];
}

int main() {
  int n;
  scanf("%d", &n);
  for (int i = 0; i < n; i++) {
    scanf("%d", type + i);
  }
  for (int i = 0; i < n; i++) {
    scanf("%d", &ev[i].first);
    ev[i].second = i;
  }
  sort(ev, ev + n);
  int cur_label = 0;
  for (int i = 0; i < n; i++) {
    if (i > 0 && ev[i].first != ev[i - 1].first) {
      cur_label++;
    }
    label[ev[i].second] = cur_label;
  }
  for (int i = 0; i < n - 1; i++) {
    int foo, bar;
    scanf("%d %d", &foo, &bar);
    foo--; bar--;
    g[foo].push_back(bar);
    g[bar].push_back(foo);
  }
  int tt;
  scanf("%d", &tt);
  pv[0] = 0;
  depth[0] = 0;
  dfs(0, -1);
  for (int i = 0; i < n; i++) {
    pr[i][0] = pv[i];
  }
  for (int j = 1; j < LOG; j++) {
    for (int i = 0; i < n; i++) {
      pr[i][j] = pr[pr[i][j - 1]][j - 1];
    }
  }
  int cnt = 0;
  for (int i = 0; i < tt; i++) {
    int w, x, y, z;
    scanf("%d %d", &w, &x);
    y = w; z = x;
    w--; x--; y--; z--;
    vector < pair <int, int> > a, b;
    {
      int LCA = lca(w, x);
      a.push_back(make_pair(w, 1));
      a.push_back(make_pair(x, 1));
      a.push_back(make_pair(LCA, -1));
      if (LCA != 0) {
        a.push_back(make_pair(pv[LCA], -1));
      }
    }
    {
      int LCA = lca(y, z);
      b.push_back(make_pair(y, 1));
      b.push_back(make_pair(z, 1));
      b.push_back(make_pair(LCA, -1));
      if (LCA != 0) {
        b.push_back(make_pair(pv[LCA], -1));
      }
    }
    for (int ia = 0; ia < (int) a.size(); ia++) {
      for (int ib = 0; ib < (int) b.size(); ib++) {
        Query &q = qs[cnt++];
        q.a = entry[a[ia].first];
        q.b = entry[b[ib].first];
        q.coeff = a[ia].second * b[ib].second;
        q.id = i;
//        result[i] -= q.coeff * (depth[lca(order[q.a], order[q.b])] + 1);
//        cerr << "query " << q.a << " " << q.b << " " << q.coeff << " " << q.id << " -> " << result[i] << endl;
      }
    }
  }
  BLOCK = (int) (1 + sqrt(order.size()));
  sort(qs, qs + cnt, cmp);
  long long sum = 0;
  int x = -1, y = -1;
  for (int id = 0; id < cnt; id++) {
    Query &q = qs[id];
    while (x < q.a) {
      x++;
      if (type[order[x] >= 0 ? order[x] : ~order[x]] == 0) {
        if (order[x] >= 0) {
          sum += in_b[label[order[x]]];
          in_a[label[order[x]]]++;
        } else {
          sum -= in_b[label[~order[x]]];
          in_a[label[~order[x]]]--;
        }
      }
    }
    while (y < q.b) {
      y++;
      if (type[order[y] >= 0 ? order[y] : ~order[y]] == 1) {
        if (order[y] >= 0) {
          sum += in_a[label[order[y]]];
          in_b[label[order[y]]]++;
        } else {
          sum -= in_a[label[~order[y]]];
          in_b[label[~order[y]]]--;
        }
      }
    }
    while (x > q.a) {
      if (type[order[x] >= 0 ? order[x] : ~order[x]] == 0) {
        if (order[x] >= 0) {
          sum -= in_b[label[order[x]]];
          in_a[label[order[x]]]--;
        } else {
          sum += in_b[label[~order[x]]];
          in_a[label[~order[x]]]++;
        }
      }
      x--;
    }
    while (y > q.b) {
      if (type[order[y] >= 0 ? order[y] : ~order[y]] == 1) {
        if (order[y] >= 0) {
          sum -= in_a[label[order[y]]];
          in_b[label[order[y]]]--;
        } else {
          sum += in_a[label[~order[y]]];
          in_b[label[~order[y]]]++;
        }
      }
      y--;
    }
    result[q.id] += q.coeff * sum;
  }
  for (int i = 0; i < tt; i++) {
    printf("%lld\n", result[i]);
  }
  return 0;
}


/**
 *    author:  tourist
 *    created: 03.09.2017 13:50:22
**/

// HackerRank University CodeSprint, problem "Counting On a Tree", modified

#include <bits/stdc++.h>

using namespace std;

struct Query {
  int a;
  int b;
  int coeff;
  int id;
};

int BLOCK;

inline bool cmp(Query &x, Query &y) {
  int X = x.a / BLOCK;
  int Y = y.a / BLOCK;
  if (X != Y) {
    return X < Y;
  }
  return x.b < y.b;
}

const int N = 200010;
const int LOG = 20;

vector <int> order;
int entry[N], brexit[N];
int pv[N];
int pr[N][LOG];
Query qs[N];
long long result[N];
int in_a[N], in_b[N];
int label[N];
vector <int> g[N];
int depth[N];
pair <int, int> ev[N];
int type[N];

void dfs(int v, int pr) {
  entry[v] = order.size();
  order.push_back(v);
  int sz = g[v].size();
  for (int j = 0; j < sz; j++) {
    int u = g[v][j];
    if (u != pr) {
      pv[u] = v;
      depth[u] = depth[v] + 1;
      dfs(u, v);
    }
  }
  brexit[v] = order.size();
  order.push_back(~v);
}

inline bool anc(int x, int y) {
  return (entry[x] <= entry[y] && brexit[y] <= brexit[x]);
}

inline int lca(int x, int y) {
  if (anc(x, y)) {
    return x;
  }
  for (int j = LOG - 1; j >= 0; j--) {
    if (!anc(pr[x][j], y)) {
      x = pr[x][j];
    }
  }
  return pr[x][0];
}

int main() {
  int n;
  scanf("%d", &n);
  for (int i = 0; i < n; i++) {
    scanf("%d", type + i);
  }
  for (int i = 0; i < n; i++) {
    scanf("%d", &ev[i].first);
    ev[i].second = i;
  }
  sort(ev, ev + n);
  int cur_label = 0;
  for (int i = 0; i < n; i++) {
    if (i > 0 && ev[i].first != ev[i - 1].first) {
      cur_label++;
    }
    label[ev[i].second] = cur_label;
  }
  for (int i = 0; i < n - 1; i++) {
    int foo, bar;
    scanf("%d %d", &foo, &bar);
    foo--; bar--;
    g[foo].push_back(bar);
    g[bar].push_back(foo);
  }
  int tt;
  scanf("%d", &tt);
  pv[0] = 0;
  depth[0] = 0;
  dfs(0, -1);
  for (int i = 0; i < n; i++) {
    pr[i][0] = pv[i];
  }
  for (int j = 1; j < LOG; j++) {
    for (int i = 0; i < n; i++) {
      pr[i][j] = pr[pr[i][j - 1]][j - 1];
    }
  }
  int cnt = 0;
  for (int i = 0; i < tt; i++) {
    int w, x, y, z;
    scanf("%d %d", &w, &x);
    y = w; z = x;
    w--; x--; y--; z--;
    vector < pair <int, int> > a, b;
    {
      int LCA = lca(w, x);
      a.push_back(make_pair(w, 1));
      a.push_back(make_pair(x, 1));
      a.push_back(make_pair(LCA, -1));
      if (LCA != 0) {
        a.push_back(make_pair(pv[LCA], -1));
      }
    }
    {
      int LCA = lca(y, z);
      b.push_back(make_pair(y, 1));
      b.push_back(make_pair(z, 1));
      b.push_back(make_pair(LCA, -1));
      if (LCA != 0) {
        b.push_back(make_pair(pv[LCA], -1));
      }
    }
    for (int ia = 0; ia < (int) a.size(); ia++) {
      for (int ib = 0; ib < (int) b.size(); ib++) {
        Query &q = qs[cnt++];
        q.a = entry[a[ia].first];
        q.b = entry[b[ib].first];
        q.coeff = a[ia].second * b[ib].second;
        q.id = i;
//        result[i] -= q.coeff * (depth[lca(order[q.a], order[q.b])] + 1);
//        cerr << "query " << q.a << " " << q.b << " " << q.coeff << " " << q.id << " -> " << result[i] << endl;
      }
    }
  }
  BLOCK = (int) (1 + sqrt(order.size()));
  sort(qs, qs + cnt, cmp);
  long long sum = 0;
  int x = -1, y = -1;
  for (int id = 0; id < cnt; id++) {
    Query &q = qs[id];
    while (x < q.a) {
      x++;
      if (type[order[x] >= 0 ? order[x] : ~order[x]] == 0) {
        if (order[x] >= 0) {
          sum += in_b[label[order[x]]];
          in_a[label[order[x]]]++;
        } else {
          sum -= in_b[label[~order[x]]];
          in_a[label[~order[x]]]--;
        }
      }
    }
    while (y < q.b) {
      y++;
      if (type[order[y] >= 0 ? order[y] : ~order[y]] == 1) {
        if (order[y] >= 0) {
          sum += in_a[label[order[y]]];
          in_b[label[order[y]]]++;
        } else {
          sum -= in_a[label[~order[y]]];
          in_b[label[~order[y]]]--;
        }
      }
    }
    while (x > q.a) {
      if (type[order[x] >= 0 ? order[x] : ~order[x]] == 0) {
        if (order[x] >= 0) {
          sum -= in_b[label[order[x]]];
          in_a[label[order[x]]]--;
        } else {
          sum += in_b[label[~order[x]]];
          in_a[label[~order[x]]]++;
        }
      }
      x--;
    }
    while (y > q.b) {
      if (type[order[y] >= 0 ? order[y] : ~order[y]] == 1) {
        if (order[y] >= 0) {
          sum -= in_a[label[order[y]]];
          in_b[label[order[y]]]--;
        } else {
          sum += in_a[label[~order[y]]];
          in_b[label[~order[y]]]++;
        }
      }
      y--;
    }
    result[q.id] += q.coeff * sum;
  }
  for (int i = 0; i < tt; i++) {
    printf("%lld\n", result[i]);
  }
  return 0;
}


#include <iostream>
#include <vector>
#include <algorithm>
#include <cmath>
#include <cstdio>

using namespace std;
#define FR(i,n) for(int i = 0,__end=(n); i < __end; ++i)
struct LCA {
    vector<vector<int> > par;
    vector<int> dep;
    vector<vector<int> > & adj;
    int log;

    LCA(int n, int root, vector<vector<int> > &_adj):adj(_adj) {

        for (log = 1; (1 << log) < n; log++);
        par.resize(n, vector<int>(log, -1));
        dep.resize(n,0);
        dfs(root, -1);
        for(int j = 1; j < log;++j)
            for(int i = 0 ; i < n; ++i) {
                if(par[i][j-1] != -1) {
                    par[i][j] = par[par[i][j-1]][j - 1];
                }
            }
    }

    void dfs(int v, int p) {
        par[v][0] = p;
        if(p != -1) {
            dep[v] = dep[p] + 1;
        }

        for(vector<int>::iterator it = adj[v].begin(); it != adj[v].end(); ++it) {
            int u = *it;
            if(u != p) {
                dfs(u,v);
            }
        }
    }

    int getLCA(int a, int b) {
        if (dep[a] > dep[b]) return getLCA(b, a);
        for (int i = log - 1; i >= 0; i--) {
            if (par[b][i] != -1 && dep[par[b][i]] >= dep[a]) {
                b = par[b][i];
            }
        }
        if (a == b) return a;
        for (int i = log - 1; i >= 0; i--) {
            if (par[a][i] != par[b][i]) {
                a = par[a][i];
                b = par[b][i];
            }
        }
        return par[a][0];
    }
};

struct MoData {
    int l,r,add,id;
};

const int MAXN = 100100;
vector<vector<int> > g;
int n;
int cnt[MAXN] = {0};
int f[MAXN];
int ff[MAXN];
bool isGirl[MAXN];
int npath = 0;
int path[2 * MAXN];
int val,to,from,q,p;
int st[MAXN];
int en[MAXN];
MoData mo[MAXN];
int blockSize = 1024;
LCA * lca;
int countBoy[MAXN] = {0},countGirl[MAXN] = {0};
long long re = 0;
long long ret[MAXN];

void _add(int f, bool girl, int delta) {
    re -= 1ll * countGirl[f] * countBoy[f];
    if(girl) countGirl[f]+=delta; else countBoy[f] += delta;
    re += 1ll * countGirl[f] * countBoy[f];
}

void moAdd(int pos) {
    int id = path[pos];
    cnt[id] ^= 1;
    if(cnt[id] == 1) _add(f[id],isGirl[id], 1); else _add(f[id],isGirl[id],-1);
}

void moRemove(int pos) {
    int id = path[pos];
    if(cnt[id] == 1) _add(f[id],isGirl[id], -1); else _add(f[id],isGirl[id],1);
    cnt[id] ^= 1;
}

bool moDataCmp(const MoData& m1, const MoData& m2) {
    // int b1 = m1.l/blockSize;
    // int b2 = m2.l/blockSize;
    // if(b1 != b2) return b1 < b2;

    if((m1.l >> 9) != (m2.l>>9)) return m1.l < m2.l;
    return m1.r < m2.r;
}
void dfs(int v, int par) {
    st[v] = npath;
    path[npath++ ] = v;
    FR(i, g[v].size()) {
        int u = g[v][i];
        if(u != par) {
            dfs(u,v);
        }
    }

    en[v] = npath;
    path[npath++] = v;
}

int main () {
    ios_base::sync_with_stdio(false);
    cin.tie(0);
    cout.tie(0);
    //cin>>n;
    scanf("%d",&n);
    FR(i,n) {
        //cin>>val;
        scanf("%d",&val);
        isGirl[i] = (1 == val);
    }
    FR(i,n) {
        //cin>>f[i];
        scanf("%d",&f[i]);
        ff[i] = f[i];
    }
    sort(ff, ff + n);
    FR(i,n) f[i] = lower_bound(ff, ff + n, f[i]) - ff;
    g.resize(n);
    FR(i,n - 1) {
        //cin>>from>>to;
        scanf("%d%d",&from,&to);
        from--; to --;
        g[from].push_back(to);
        g[to].push_back(from);
    }
    dfs(0, -1);
    lca = new LCA(n, 0 , g);

    cin>>q;
    FR(i,q) {
        //cin>>from>>to;
        scanf("%d%d",&from,&to);
        from--;to--;
        if(st[from] > st[to]) swap(from,to);
        p = lca->getLCA(from, to);
        mo[i].id = i;
        if(from == p) {
            mo[i].l = st[from];
            mo[i].r = st[to];
            mo[i].add = -1;
        } else {
            mo[i].l = en[from];
            mo[i].r = st[to];
            mo[i].add = p;
        }
    }

    //blockSize = (int)sqrt(npath) + 1;

    sort(mo, mo + q, moDataCmp);
    int moStart = mo[0].l;
    int moEnd = moStart - 1;
    // FR(i,npath) cerr<<path[i]<<" ";
    // cerr<<endl;

    FR(i,q) {
        int l = mo[i].l;
        int r = mo[i].r;
        while(moStart < l) moRemove(moStart ++);
        while(moStart > l) moAdd(--moStart);
        while(moEnd < r) moAdd(++moEnd);
        while(moEnd > r) moRemove(moEnd--);
        if(mo[i].add == -1) {
            ret[mo[i].id] = re;
        } else {
            int p = mo[i].add;
            _add(f[p], isGirl[p], 1);
            ret[mo[i].id] = re;
            _add(f[p], isGirl[p], -1);
        }
    }

    FR(i,q) printf("%lld\n",ret[i]);

    delete lca;
    return 0;
}


#include <bits/stdc++.h>
using namespace std;
typedef long long ll;

const int MAXN = 100005;
const int MAXM = 100005;
const int LN = 18;

int N, M, K, cur, A[MAXN], LVL[MAXN], DP[LN][MAXN], TP[MAXN];
int BL[MAXN << 1], ID[MAXN << 1], VAL[2][MAXN];
ll ANS[MAXM];
int d[MAXN], l[MAXN], r[MAXN];
bool VIS[MAXN];
vector < int > adjList[MAXN];

struct query{
	int id, l, r, lc;
	bool operator < (const query& rhs){
		return (BL[l] == BL[rhs.l]) ? (r < rhs.r) : (BL[l] < BL[rhs.l]);
	}
}Q[MAXM];

// Set up Stuff
void dfs(int u, int par){
	l[u] = ++cur;
	ID[cur] = u;
	for (int i = 1; i < LN; i++) DP[i][u] = DP[i - 1][DP[i - 1][u]];
	for (int i = 0; i < adjList[u].size(); i++){
		int v = adjList[u][i];
		if (v == par) continue;
		LVL[v] = LVL[u] + 1;
		DP[0][v] = u;
		dfs(v, u);
	}
	r[u] = ++cur; ID[cur] = u;
}

// Function returns lca of (u) and (v)
inline int lca(int u, int v){
	if (LVL[u] > LVL[v]) swap(u, v);
	for (int i = LN - 1; i >= 0; i--)
		if (LVL[v] - (1 << i) >= LVL[u]) v = DP[i][v];
	if (u == v) return u;
	for (int i = LN - 1; i >= 0; i--){
		if (DP[i][u] != DP[i][v]){
			u = DP[i][u];
			v = DP[i][v];
		}
	}
	return DP[0][u];
}

inline void check(int x, ll& res){
	// If (x) occurs twice, then don't consider it's value
	if (VIS[x]) {
    --VAL[TP[x]][A[x]];
    res -= VAL[1-TP[x]][A[x]];
  }
	else {
    res += VAL[1-TP[x]][A[x]];
    ++VAL[TP[x]][A[x]];
  }
	VIS[x] ^= 1;
}

void compute(){

	// Perform standard Mo's Algorithm
	int curL = Q[0].l, curR = Q[0].l - 1;
  ll res = 0;

	for (int i = 0; i < M; i++){

		while (curL < Q[i].l) check(ID[curL++], res);
		while (curL > Q[i].l) check(ID[--curL], res);
		while (curR < Q[i].r) check(ID[++curR], res);
		while (curR > Q[i].r) check(ID[curR--], res);

		int u = ID[curL], v = ID[curR];

		// Case 2
		if (Q[i].lc != u and Q[i].lc != v) check(Q[i].lc, res);

		ANS[Q[i].id] = res;

		if (Q[i].lc != u and Q[i].lc != v) check(Q[i].lc, res);
	}

	for (int i = 0; i < M; i++) printf("%lld\n", ANS[i]);
}

int main(){

	int u, v, x;

	while (scanf("%d", &N) != EOF){

		// Cleanup
		cur = 0;
		memset(VIS, 0, sizeof(VIS));
		memset(VAL, 0, sizeof(VAL));
		for (int i = 1; i <= N; i++) adjList[i].clear();

		// Inputting Values
		for (int i = 1; i <= N; i++) scanf("%d", &TP[i]);
		for (int i = 1; i <= N; i++) scanf("%d", &A[i]);
		memcpy(d + 1, A + 1, sizeof(int) * N);

		// Compressing Coordinates
		sort(d + 1, d + N + 1);
		K = unique(d + 1, d + N + 1) - d - 1;
		for (int i = 1; i <= N; i++) A[i] = lower_bound(d + 1, d + K + 1, A[i]) - d;

		// Inputting Tree
		for (int i = 1; i < N; i++){
			scanf("%d %d", &u, &v);
			adjList[u].push_back(v);
			adjList[v].push_back(u);
		}

    scanf("%d", &M);

		// Preprocess
		DP[0][1] = 1;
		dfs(1, -1);
		int size = sqrt(cur);

		for (int i = 1; i <= cur; i++) BL[i] = (i - 1) / size + 1;

		for (int i = 0; i < M; i++){
			scanf("%d %d", &u, &v);
			Q[i].lc = lca(u, v);
			if (l[u] > l[v]) swap(u, v);
			if (Q[i].lc == u) Q[i].l = l[u], Q[i].r = l[v];
			else Q[i].l = r[u], Q[i].r = l[v];
			Q[i].id = i;
		}

		sort(Q, Q + M);
		compute();

		//xx
	}
}


#include <iostream>
#include <vector>
#include <algorithm>
#include <cmath>
#include <cstdio>

using namespace std;
#define FR(i,n) for(int i = 0,__end=(n); i < __end; ++i)
struct LCA {
    vector<vector<int> > par;
    vector<int> dep;
    vector<vector<int> > & adj;
    int log;

    LCA(int n, int root, vector<vector<int> > &_adj):adj(_adj) {

        for (log = 1; (1 << log) < n; log++);
        par.resize(n, vector<int>(log, -1));
        dep.resize(n,0);
        dfs(root, -1);
        for(int j = 1; j < log;++j)
            for(int i = 0 ; i < n; ++i) {
                if(par[i][j-1] != -1) {
                    par[i][j] = par[par[i][j-1]][j - 1];
                }
            }
    }

    void dfs(int v, int p) {
        par[v][0] = p;
        if(p != -1) {
            dep[v] = dep[p] + 1;
        }

        for(vector<int>::iterator it = adj[v].begin(); it != adj[v].end(); ++it) {
            int u = *it;
            if(u != p) {
                dfs(u,v);
            }
        }
    }

    int getLCA(int a, int b) {
        if (dep[a] > dep[b]) return getLCA(b, a);
        for (int i = log - 1; i >= 0; i--) {
            if (par[b][i] != -1 && dep[par[b][i]] >= dep[a]) {
                b = par[b][i];
            }
        }
        if (a == b) return a;
        for (int i = log - 1; i >= 0; i--) {
            if (par[a][i] != par[b][i]) {
                a = par[a][i];
                b = par[b][i];
            }
        }
        return par[a][0];
    }
};

struct MoData {
    int l,r,add,id;
};

const int MAXN = 100100;
vector<vector<int> > g;
int n;
int cnt[MAXN] = {0};
int f[MAXN];
int ff[MAXN];
bool isGirl[MAXN];
int npath = 0;
int path[2 * MAXN];
int val,to,from,q,p;
int st[MAXN];
int en[MAXN];
MoData mo[MAXN];
int blockSize = 1024;
LCA * lca;
int countBoy[MAXN] = {0},countGirl[MAXN] = {0};
long long re = 0;
long long ret[MAXN];

void _add(int f, bool girl, int delta) {
    re -= 1ll * countGirl[f] * countBoy[f];
    if(girl) countGirl[f]+=delta; else countBoy[f] += delta;
    re += 1ll * countGirl[f] * countBoy[f];
}

void moAdd(int pos) {
    int id = path[pos];
    cnt[id] ^= 1;
    if(cnt[id] == 1) _add(f[id],isGirl[id], 1); else _add(f[id],isGirl[id],-1);
}

void moRemove(int pos) {
    int id = path[pos];
    if(cnt[id] == 1) _add(f[id],isGirl[id], -1); else _add(f[id],isGirl[id],1);
    cnt[id] ^= 1;
}

bool moDataCmp(const MoData& m1, const MoData& m2) {
    // int b1 = m1.l/blockSize;
    // int b2 = m2.l/blockSize;
    // if(b1 != b2) return b1 < b2;

    if((m1.l >> 9) != (m2.l>>9)) return m1.l < m2.l;
    return m1.r < m2.r;
}
void dfs(int v, int par) {
    st[v] = npath;
    path[npath++ ] = v;
    FR(i, g[v].size()) {
        int u = g[v][i];
        if(u != par) {
            dfs(u,v);
        }
    }

    en[v] = npath;
    path[npath++] = v;
}

int main () {
    // ios_base::sync_with_stdio(false);
    // cin.tie(0);
    // cout.tie(0);
    //cin>>n;
    scanf("%d",&n);
    FR(i,n) {
        //cin>>val;
        scanf("%d",&val);
        isGirl[i] = (1 == val);
    }
    FR(i,n) {
        //cin>>f[i];
        scanf("%d",&f[i]);
        ff[i] = f[i];
    }
    sort(ff, ff + n);
    FR(i,n) f[i] = lower_bound(ff, ff + n, f[i]) - ff;
    g.resize(n);
    FR(i,n - 1) {
        //cin>>from>>to;
        scanf("%d%d",&from,&to);
        from--; to --;
        g[from].push_back(to);
        g[to].push_back(from);
    }
    dfs(0, -1);
    lca = new LCA(n, 0 , g);

    cin>>q;
    FR(i,q) {
        //cin>>from>>to;
        scanf("%d%d",&from,&to);
        from--;to--;
        if(st[from] > st[to]) swap(from,to);
        p = lca->getLCA(from, to);
        mo[i].id = i;
        if(from == p) {
            mo[i].l = st[from];
            mo[i].r = st[to];
            mo[i].add = -1;
        } else {
            mo[i].l = en[from];
            mo[i].r = st[to];
            mo[i].add = p;
        }
    }

    //blockSize = (int)sqrt(npath) + 1;

    sort(mo, mo + q, moDataCmp);
    int moStart = mo[0].l;
    int moEnd = moStart - 1;
    // FR(i,npath) cerr<<path[i]<<" ";
    // cerr<<endl;

    FR(i,q) {
        int l = mo[i].l;
        int r = mo[i].r;
        while(moStart < l) moRemove(moStart ++);
        while(moStart > l) moAdd(--moStart);
        while(moEnd < r) moAdd(++moEnd);
        while(moEnd > r) moRemove(moEnd--);
        if(mo[i].add == -1) {
            ret[mo[i].id] = re;
        } else {
            int p = mo[i].add;
            _add(f[p], isGirl[p], 1);
            ret[mo[i].id] = re;
            _add(f[p], isGirl[p], -1);
        }
    }

    FR(i,q) printf("%lld\n",ret[i]);

    delete lca;
    return 0;
}


#include <iostream>
#include <vector>
#include <algorithm>
#include <cmath>
#include <cstdio>

using namespace std;
#define FR(i,n) for(int i = 0,__end=(n); i < __end; ++i)

struct MoData {
    int l,r,add,id;

};

const int MAXN = 100100;
//vector<vector<int> > g;

vector<int> g[MAXN];
int dep[MAXN];
int par[MAXN][20];
int LOG = 0;
int n;
int cnt[MAXN] = {0};
int f[MAXN];
int ff[MAXN];
int isGirl[MAXN];
int npath = 0;
int path[2 * MAXN];
int val,to,from,q,p;
int st[MAXN];
int en[MAXN];
MoData mo[MAXN];
int blockSize = 1024;
int BL[MAXN * 2];

int countVal[MAXN][2] = {0};
long long re = 0;
long long ret[MAXN];

int getLCA(int a, int b) {
    if (dep[a] > dep[b]) return getLCA(b, a);
    for (int i = LOG - 1; i >= 0; i--) {
        if (par[b][i] != -1 && dep[par[b][i]] >= dep[a]) {
            b = par[b][i];
        }
    }
    if (a == b) return a;
    for (int i = LOG - 1; i >= 0; i--) {
        if (par[a][i] != par[b][i]) {
            a = par[a][i];
            b = par[b][i];
        }
    }
    return par[a][0];
}

void vao(int pos) {
    int id = path[pos];
    if(cnt[id] == 1) {
        countVal[f[id]][isGirl[id]]--;
        re -= countVal[f[id]][isGirl[id]^1];
    } else {
        countVal[f[id]][isGirl[id]]++;
        re += countVal[f[id]][isGirl[id]^1];
    }
    cnt[id] ^= 1;
}

bool moDataCmp(const MoData& m1, const MoData& m2) {
    if(BL[m1.l] != BL[m2.l]) return BL[m1.l] < BL[m2.l]; else return m1.r < m2.r;

    // if((m1.l >> 9) != (m2.l>>9)) return m1.l < m2.l;
    // return m1.r < m2.r;
}
void dfs(int v, int p) {
    par[v][0] = p;
    if(p != -1) {
        dep[v] = dep[p] + 1;
    }

    st[v] = ++npath;
    path[npath ] = v;
    FR(i, g[v].size()) {
        int u = g[v][i];
        if(u != p) {
            dfs(u,v);
        }
    }

    en[v] = ++npath;
    path[npath] = v;
}

int main () {
    // ios_base::sync_with_stdio(false);
    // cin.tie(0);
    // cout.tie(0);
    //cin>>n;xx
    scanf("%d",&n);
    FR(i,n) {
        //cin>>val;
        scanf("%d",&val);
        isGirl[i] = (1 == val);
    }
    FR(i,n) {
        //cin>>f[i];
        scanf("%d",&f[i]);
        ff[i] = f[i];
    }
    sort(ff, ff + n);
    int nf = unique(ff, ff + n) - ff;
    FR(i,n) f[i] = lower_bound(ff, ff + nf, f[i]) - ff;

    FR(i,n - 1) {
        //cin>>from>>to;
        scanf("%d%d",&from,&to);
        from--; to --;
        g[from].push_back(to);
        g[to].push_back(from);
    }
    for (LOG = 1; (1 << LOG) < n; LOG++);
    dfs(0, -1);
    for(int j = 1; j < LOG;++j)
        for(int i = 0 ; i < n; ++i) {
            if(par[i][j-1] != -1) {
                par[i][j] = par[par[i][j-1]][j - 1];
            }
        }

    cin>>q;
    FR(i,q) {
        //cin>>from>>to;
        scanf("%d%d",&from,&to);
        from--;to--;
        if(st[from] > st[to]) swap(from,to);
        p = getLCA(from, to);
        mo[i].id = i;
        if(from == p) {
            mo[i].l = st[from];
            mo[i].r = st[to];
            mo[i].add = -1;
        } else {
            mo[i].l = en[from];
            mo[i].r = st[to];
            mo[i].add = p;
        }
    }

    blockSize = sqrt(npath) ;
    for(int i = 1 ; i<= npath; ++i) BL[i] = (i - 1)/blockSize + 1 ;
    sort(mo, mo + q, moDataCmp);
    int moStart = mo[0].l;
    int moEnd = moStart - 1;
    // FR(i,npath) cerr<<path[i]<<" ";
    // cerr<<endl;

    FR(i,q) {
        int l = mo[i].l;
        int r = mo[i].r;
        while(moStart < l) vao(moStart ++);
        while(moStart > l) vao(--moStart);
        while(moEnd < r) vao(++moEnd);
        while(moEnd > r) vao(moEnd--);
        if(mo[i].add == -1) {
            ret[mo[i].id] = re;
        } else {
            int p = mo[i].add;
            vao(st[p]);
            ret[mo[i].id] = re;
            vao(st[p]);
        }
    }

    FR(i,q) printf("%lld\n",ret[i]);

    return 0;
}


#include <iostream>
#include <vector>
#include <algorithm>
#include <cmath>
#include <cstdio>

using namespace std;
#define FR(i,n) for(int i = 0,__end=(n); i < __end; ++i)

struct MoData {
    int l,r,add,id;

};

const int MAXN = 100100;
//vector<vector<int> > g;

vector<int> g[MAXN];
int dep[MAXN];
int par[MAXN][20];
int LOG = 0;
int n;
int cnt[MAXN] = {0};
int f[MAXN];
int ff[MAXN];
bool isGirl[MAXN];
int npath = 0;
int path[2 * MAXN];
int val,to,from,q,p;
int st[MAXN];
int en[MAXN];
MoData mo[MAXN];
int blockSize = 1024;
int BL[MAXN * 2];

int countBoy[MAXN] = {0},countGirl[MAXN] = {0};
long long re = 0;
long long ret[MAXN];

int getLCA(int a, int b) {
    if (dep[a] > dep[b]) return getLCA(b, a);
    for (int i = LOG - 1; i >= 0; i--) {
        if (par[b][i] != -1 && dep[par[b][i]] >= dep[a]) {
            b = par[b][i];
        }
    }
    if (a == b) return a;
    for (int i = LOG - 1; i >= 0; i--) {
        if (par[a][i] != par[b][i]) {
            a = par[a][i];
            b = par[b][i];
        }
    }
    return par[a][0];
}

void _add(int f, bool girl, int delta) {
    re -= 1ll * countGirl[f] * countBoy[f];
    if(girl) countGirl[f]+=delta; else countBoy[f] += delta;
    re += 1ll * countGirl[f] * countBoy[f];
}

void moAdd(int pos) {
    int id = path[pos];
    cnt[id] ^= 1;
    if(cnt[id] == 1) _add(f[id],isGirl[id], 1); else _add(f[id],isGirl[id],-1);
}

void moRemove(int pos) {
    int id = path[pos];
    if(cnt[id] == 1) _add(f[id],isGirl[id], -1); else _add(f[id],isGirl[id],1);
    cnt[id] ^= 1;
}

bool moDataCmp(const MoData& m1, const MoData& m2) {
    if(BL[m1.l] != BL[m2.l]) return BL[m1.l] < BL[m2.l]; else return m1.r < m2.r;

    // if((m1.l >> 9) != (m2.l>>9)) return m1.l < m2.l;
    // return m1.r < m2.r;
}
void dfs(int v, int p) {
    par[v][0] = p;
    if(p != -1) {
        dep[v] = dep[p] + 1;
    }

    st[v] = ++npath;
    path[npath ] = v;
    FR(i, g[v].size()) {
        int u = g[v][i];
        if(u != p) {
            dfs(u,v);
        }
    }

    en[v] = ++npath;
    path[npath] = v;
}

int main () {
    // ios_base::sync_with_stdio(false);
    // cin.tie(0);
    // cout.tie(0);
    //cin>>n;xx
    scanf("%d",&n);
    FR(i,n) {
        //cin>>val;
        scanf("%d",&val);
        isGirl[i] = (1 == val);
    }
    FR(i,n) {
        //cin>>f[i];
        scanf("%d",&f[i]);
        ff[i] = f[i];
    }
    sort(ff, ff + n);
    int nf = unique(ff, ff + n) - ff;
    FR(i,n) f[i] = lower_bound(ff, ff + nf, f[i]) - ff;

    FR(i,n - 1) {
        //cin>>from>>to;
        scanf("%d%d",&from,&to);
        from--; to --;
        g[from].push_back(to);
        g[to].push_back(from);
    }
    for (LOG = 1; (1 << LOG) < n; LOG++);
    dfs(0, -1);
    for(int j = 1; j < LOG;++j)
        for(int i = 0 ; i < n; ++i) {
            if(par[i][j-1] != -1) {
                par[i][j] = par[par[i][j-1]][j - 1];
            }
        }

    cin>>q;
    FR(i,q) {
        //cin>>from>>to;
        scanf("%d%d",&from,&to);
        from--;to--;
        if(st[from] > st[to]) swap(from,to);
        p = getLCA(from, to);
        mo[i].id = i;
        if(from == p) {
            mo[i].l = st[from];
            mo[i].r = st[to];
            mo[i].add = -1;
        } else {
            mo[i].l = en[from];
            mo[i].r = st[to];
            mo[i].add = p;
        }
    }

    blockSize = sqrt(npath) ;
    for(int i = 1 ; i<= npath; ++i) BL[i] = (i - 1)/blockSize + 1 ;
    sort(mo, mo + q, moDataCmp);
    int moStart = mo[0].l;
    int moEnd = moStart - 1;
    // FR(i,npath) cerr<<path[i]<<" ";
    // cerr<<endl;

    FR(i,q) {
        int l = mo[i].l;
        int r = mo[i].r;
        while(moStart < l) moRemove(moStart ++);
        while(moStart > l) moAdd(--moStart);
        while(moEnd < r) moAdd(++moEnd);
        while(moEnd > r) moRemove(moEnd--);
        if(mo[i].add == -1) {
            ret[mo[i].id] = re;
        } else {
            int p = mo[i].add;
            _add(f[p], isGirl[p], 1);
            ret[mo[i].id] = re;
            _add(f[p], isGirl[p], -1);
        }
    }

    FR(i,q) printf("%lld\n",ret[i]);

    return 0;
}


#include <iostream>
#include <vector>
#include <algorithm>
#include <cmath>
#include <cstdio>

using namespace std;
#define FR(i,n) for(int i = 0,__end=(n); i < __end; ++i)

struct MoData {
    int l,r,add,id;

};

const int MAXN = 100100;
//vector<vector<int> > g;

vector<int> g[MAXN];
int dep[MAXN];
int par[MAXN][20];
int LOG = 0;
int n;
int cnt[MAXN] = {0};
int f[MAXN];
int ff[MAXN];
bool isGirl[MAXN];
int npath = 0;
int path[2 * MAXN];
int val,to,from,q,p;
int st[MAXN];
int en[MAXN];
MoData mo[MAXN];
int blockSize = 1024;
int BL[MAXN * 2];

int countBoy[MAXN] = {0},countGirl[MAXN] = {0};
long long re = 0;
long long ret[MAXN];

int getLCA(int a, int b) {
    if (dep[a] > dep[b]) return getLCA(b, a);
    for (int i = LOG - 1; i >= 0; i--) {
        if (par[b][i] != -1 && dep[par[b][i]] >= dep[a]) {
            b = par[b][i];
        }
    }
    if (a == b) return a;
    for (int i = LOG - 1; i >= 0; i--) {
        if (par[a][i] != par[b][i]) {
            a = par[a][i];
            b = par[b][i];
        }
    }
    return par[a][0];
}

void _add(int f, bool girl, int delta) {
    re -= 1ll * countGirl[f] * countBoy[f];
    if(girl) countGirl[f]+=delta; else countBoy[f] += delta;
    re += 1ll * countGirl[f] * countBoy[f];
}

void moAdd(int pos) {
    int id = path[pos];
    cnt[id] ^= 1;
    if(cnt[id] == 1) _add(f[id],isGirl[id], 1); else _add(f[id],isGirl[id],-1);
}

void moRemove(int pos) {
    int id = path[pos];
    if(cnt[id] == 1) _add(f[id],isGirl[id], -1); else _add(f[id],isGirl[id],1);
    cnt[id] ^= 1;
}

bool moDataCmp(const MoData& m1, const MoData& m2) {
    if(BL[m1.l] != BL[m2.l]) return BL[m1.l] < BL[m2.l]; else return m1.r < m2.r;

    // if((m1.l >> 9) != (m2.l>>9)) return m1.l < m2.l;
    // return m1.r < m2.r;
}
void dfs(int v, int p) {
    par[v][0] = p;
    if(p != -1) {
        dep[v] = dep[p] + 1;
    }

    st[v] = npath;
    path[npath++ ] = v;
    FR(i, g[v].size()) {
        int u = g[v][i];
        if(u != p) {
            dfs(u,v);
        }
    }

    en[v] = npath;
    path[npath++] = v;
}

int main () {
    // ios_base::sync_with_stdio(false);
    // cin.tie(0);
    // cout.tie(0);
    //cin>>n;
    scanf("%d",&n);
    FR(i,n) {
        //cin>>val;
        scanf("%d",&val);
        isGirl[i] = (1 == val);
    }
    FR(i,n) {
        //cin>>f[i];
        scanf("%d",&f[i]);
        ff[i] = f[i];
    }
    sort(ff, ff + n);
    FR(i,n) f[i] = lower_bound(ff, ff + n, f[i]) - ff;

    FR(i,n - 1) {
        //cin>>from>>to;
        scanf("%d%d",&from,&to);
        from--; to --;
        g[from].push_back(to);
        g[to].push_back(from);
    }
    for (LOG = 1; (1 << LOG) < n; LOG++);
    dfs(0, -1);
    for(int j = 1; j < LOG;++j)
        for(int i = 0 ; i < n; ++i) {
            if(par[i][j-1] != -1) {
                par[i][j] = par[par[i][j-1]][j - 1];
            }
        }

    cin>>q;
    FR(i,q) {
        //cin>>from>>to;
        scanf("%d%d",&from,&to);
        from--;to--;
        if(st[from] > st[to]) swap(from,to);
        p = getLCA(from, to);
        mo[i].id = i;
        if(from == p) {
            mo[i].l = st[from];
            mo[i].r = st[to];
            mo[i].add = -1;
        } else {
            mo[i].l = en[from];
            mo[i].r = st[to];
            mo[i].add = p;
        }
    }

    blockSize = (int)sqrt(npath) ;
    FR(i,npath) BL[i] = i/blockSize + 1;
    sort(mo, mo + q, moDataCmp);
    int moStart = mo[0].l;
    int moEnd = moStart - 1;
    // FR(i,npath) cerr<<path[i]<<" ";
    // cerr<<endl;

    FR(i,q) {
        int l = mo[i].l;
        int r = mo[i].r;
        while(moStart < l) moRemove(moStart ++);
        while(moStart > l) moAdd(--moStart);
        while(moEnd < r) moAdd(++moEnd);
        while(moEnd > r) moRemove(moEnd--);
        if(mo[i].add == -1) {
            ret[mo[i].id] = re;
        } else {
            int p = mo[i].add;
            _add(f[p], isGirl[p], 1);
            ret[mo[i].id] = re;
            _add(f[p], isGirl[p], -1);
        }
    }

    FR(i,q) printf("%lld\n",ret[i]);

    return 0;
}


#include <iostream>
#include <vector>
#include <algorithm>
#include <cmath>
#include <cstdio>

using namespace std;
#define FR(i,n) for(int i = 0,__end=(n); i < __end; ++i)

struct MoData {
    int l,r,add,id;

};

const int MAXN = 100100;
//vector<vector<int> > g;

vector<int> g[MAXN];
int dep[MAXN];
int par[MAXN][20];
int LOG = 0;
int n;
int cnt[MAXN] = {0};
int f[MAXN];
int ff[MAXN];
bool isGirl[MAXN];
int npath = 0;
int path[2 * MAXN];
int val,to,from,q,p;
int st[MAXN];
int en[MAXN];
MoData mo[MAXN];
int blockSize = 1024;
int BL[MAXN * 2];

int countBoy[MAXN] = {0},countGirl[MAXN] = {0};
long long re = 0;
long long ret[MAXN];

int getLCA(int a, int b) {
    if (dep[a] > dep[b]) return getLCA(b, a);
    for (int i = LOG - 1; i >= 0; i--) {
        if (par[b][i] != -1 && dep[par[b][i]] >= dep[a]) {
            b = par[b][i];
        }
    }
    if (a == b) return a;
    for (int i = LOG - 1; i >= 0; i--) {
        if (par[a][i] != par[b][i]) {
            a = par[a][i];
            b = par[b][i];
        }
    }
    return par[a][0];
}

void _add(int f, bool girl, int delta) {
    re -= 1ll * countGirl[f] * countBoy[f];
    if(girl) countGirl[f]+=delta; else countBoy[f] += delta;
    re += 1ll * countGirl[f] * countBoy[f];
}

void moAdd(int pos) {
    int id = path[pos];
    cnt[id] ^= 1;
    if(cnt[id] == 1) _add(f[id],isGirl[id], 1); else _add(f[id],isGirl[id],-1);
}

void moRemove(int pos) {
    int id = path[pos];
    if(cnt[id] == 1) _add(f[id],isGirl[id], -1); else _add(f[id],isGirl[id],1);
    cnt[id] ^= 1;
}

bool moDataCmp(const MoData& m1, const MoData& m2) {
    if(BL[m1.l] != BL[m2.l]) return BL[m1.l] < BL[m2.l]; else return m1.r < m2.r;

    // if((m1.l >> 9) != (m2.l>>9)) return m1.l < m2.l;
    // return m1.r < m2.r;
}
void dfs(int v, int p) {
    par[v][0] = p;
    if(p != -1) {
        dep[v] = dep[p] + 1;
    }

    st[v] = npath;
    path[npath++ ] = v;
    FR(i, g[v].size()) {
        int u = g[v][i];
        if(u != p) {
            dfs(u,v);
        }
    }

    en[v] = npath;
    path[npath++] = v;
}

int main () {
    // ios_base::sync_with_stdio(false);
    // cin.tie(0);
    // cout.tie(0);
    //cin>>n;
    scanf("%d",&n);
    FR(i,n) {
        //cin>>val;
        scanf("%d",&val);
        isGirl[i] = (1 == val);
    }
    FR(i,n) {
        //cin>>f[i];
        scanf("%d",&f[i]);
        ff[i] = f[i];
    }
    sort(ff, ff + n);
    FR(i,n) f[i] = lower_bound(ff, ff + n, f[i]) - ff;

    FR(i,n - 1) {
        //cin>>from>>to;
        scanf("%d%d",&from,&to);
        from--; to --;
        g[from].push_back(to);
        g[to].push_back(from);
    }
    for (LOG = 1; (1 << LOG) < n; LOG++);
    dfs(0, -1);
    for(int j = 1; j < LOG;++j)
        for(int i = 0 ; i < n; ++i) {
            if(par[i][j-1] != -1) {
                par[i][j] = par[par[i][j-1]][j - 1];
            }
        }

    cin>>q;
    FR(i,q) {
        //cin>>from>>to;
        scanf("%d%d",&from,&to);
        from--;to--;
        if(st[from] > st[to]) swap(from,to);
        p = getLCA(from, to);
        mo[i].id = i;
        if(from == p) {
            mo[i].l = st[from];
            mo[i].r = st[to];
            mo[i].add = -1;
        } else {
            mo[i].l = en[from];
            mo[i].r = st[to];
            mo[i].add = p;
        }
    }

    blockSize = (int)sqrt(npath) +1;
    FR(i,npath) BL[i] = i/blockSize ;
    sort(mo, mo + q, moDataCmp);
    int moStart = mo[0].l;
    int moEnd = moStart - 1;
    // FR(i,npath) cerr<<path[i]<<" ";
    // cerr<<endl;

    FR(i,q) {
        int l = mo[i].l;
        int r = mo[i].r;
        while(moStart < l) moRemove(moStart ++);
        while(moStart > l) moAdd(--moStart);
        while(moEnd < r) moAdd(++moEnd);
        while(moEnd > r) moRemove(moEnd--);
        if(mo[i].add == -1) {
            ret[mo[i].id] = re;
        } else {
            int p = mo[i].add;
            _add(f[p], isGirl[p], 1);
            ret[mo[i].id] = re;
            _add(f[p], isGirl[p], -1);
        }
    }

    FR(i,q) printf("%lld\n",ret[i]);

    return 0;
}


#include <iostream>
#include <vector>
#include <algorithm>
#include <cmath>
#include <cstdio>

using namespace std;
#define FR(i,n) for(int i = 0,__end=(n); i < __end; ++i)

struct MoData {
    int l,r,add,id;

};

const int MAXN = 100100;
//vector<vector<int> > g;

vector<int> g[MAXN];
int dep[MAXN];
int par[MAXN][20];
int LOG = 0;
int n;
int cnt[MAXN] = {0};
int f[MAXN];
int ff[MAXN];
bool isGirl[MAXN];
int npath = 0;
int path[2 * MAXN];
int val,to,from,q,p;
int st[MAXN];
int en[MAXN];
MoData mo[MAXN];
int blockSize = 1024;
int BL[MAXN * 2];

int countBoy[MAXN] = {0},countGirl[MAXN] = {0};
long long re = 0;
long long ret[MAXN];

int getLCA(int a, int b) {
    if (dep[a] > dep[b]) return getLCA(b, a);
    for (int i = LOG - 1; i >= 0; i--) {
        if (par[b][i] != -1 && dep[par[b][i]] >= dep[a]) {
            b = par[b][i];
        }
    }
    if (a == b) return a;
    for (int i = LOG - 1; i >= 0; i--) {
        if (par[a][i] != par[b][i]) {
            a = par[a][i];
            b = par[b][i];
        }
    }
    return par[a][0];
}

void _add(int f, bool girl, int delta) {
    re -= 1ll * countGirl[f] * countBoy[f];
    if(girl) countGirl[f]+=delta; else countBoy[f] += delta;
    re += 1ll * countGirl[f] * countBoy[f];
}

void moAdd(int pos) {
    int id = path[pos];
    cnt[id] ^= 1;
    if(cnt[id] == 1) _add(f[id],isGirl[id], 1); else _add(f[id],isGirl[id],-1);
}

void moRemove(int pos) {
    int id = path[pos];
    if(cnt[id] == 1) _add(f[id],isGirl[id], -1); else _add(f[id],isGirl[id],1);
    cnt[id] ^= 1;
}

bool moDataCmp(const MoData& m1, const MoData& m2) {
    if(BL[m1.l] != BL[m2.l]) return BL[m1.l] < BL[m2.l]; else return m1.r < m2.r;

    // if((m1.l >> 9) != (m2.l>>9)) return m1.l < m2.l;
    // return m1.r < m2.r;
}
void dfs(int v, int p) {
    par[v][0] = p;
    if(p != -1) {
        dep[v] = dep[p] + 1;
    }

    st[v] = ++npath;
    path[npath ] = v;
    FR(i, g[v].size()) {
        int u = g[v][i];
        if(u != p) {
            dfs(u,v);
        }
    }

    en[v] = ++npath;
    path[npath] = v;
}

int main () {
    // ios_base::sync_with_stdio(false);
    // cin.tie(0);
    // cout.tie(0);
    //cin>>n;
    scanf("%d",&n);
    FR(i,n) {
        //cin>>val;
        scanf("%d",&val);
        isGirl[i] = (1 == val);
    }
    FR(i,n) {
        //cin>>f[i];
        scanf("%d",&f[i]);
        ff[i] = f[i];
    }
    sort(ff, ff + n);
    int nf = unique(ff, ff + n) - ff;
    FR(i,n) f[i] = lower_bound(ff, ff + nf, f[i]) - ff;

    FR(i,n - 1) {
        //cin>>from>>to;
        scanf("%d%d",&from,&to);
        from--; to --;
        g[from].push_back(to);
        g[to].push_back(from);
    }
    for (LOG = 1; (1 << LOG) < n; LOG++);
    dfs(0, -1);
    for(int j = 1; j < LOG;++j)
        for(int i = 0 ; i < n; ++i) {
            if(par[i][j-1] != -1) {
                par[i][j] = par[par[i][j-1]][j - 1];
            }
        }

    cin>>q;
    FR(i,q) {
        //cin>>from>>to;
        scanf("%d%d",&from,&to);
        from--;to--;
        if(st[from] > st[to]) swap(from,to);
        p = getLCA(from, to);
        mo[i].id = i;
        if(from == p) {
            mo[i].l = st[from];
            mo[i].r = st[to];
            mo[i].add = -1;
        } else {
            mo[i].l = en[from];
            mo[i].r = st[to];
            mo[i].add = p;
        }
    }

    blockSize = sqrt(npath) ;
    for(int i = 1 ; i<= npath; ++i) BL[i] = (i - 1)/blockSize + 1 ;
    sort(mo, mo + q, moDataCmp);
    int moStart = mo[0].l;
    int moEnd = moStart - 1;
    // FR(i,npath) cerr<<path[i]<<" ";
    // cerr<<endl;

    FR(i,q) {
        int l = mo[i].l;
        int r = mo[i].r;
        while(moStart < l) moRemove(moStart ++);
        while(moStart > l) moAdd(--moStart);
        while(moEnd < r) moAdd(++moEnd);
        while(moEnd > r) moRemove(moEnd--);
        if(mo[i].add == -1) {
            ret[mo[i].id] = re;
        } else {
            int p = mo[i].add;
            _add(f[p], isGirl[p], 1);
            ret[mo[i].id] = re;
            _add(f[p], isGirl[p], -1);
        }
    }

    FR(i,q) printf("%lld\n",ret[i]);

    return 0;
}


#include <iostream>
#include <vector>
#include <algorithm>
#include <cmath>
#include <cstdio>

using namespace std;
#define FR(i,n) for(int i = 0,__end=(n); i < __end; ++i)

struct MoData {
    int l,r,add,id;

};

const int MAXN = 100100;
//vector<vector<int> > g;

vector<int> g[MAXN];
int dep[MAXN];
int par[MAXN][20];
int LOG = 0;
int n;
int cnt[MAXN] = {0};
int f[MAXN];
int ff[MAXN];
bool isGirl[MAXN];
int npath = 0;
int path[2 * MAXN];
int val,to,from,q,p;
int st[MAXN];
int en[MAXN];
MoData mo[MAXN];
int blockSize = 1024;
int BL[MAXN * 2];

int countBoy[MAXN] = {0},countGirl[MAXN] = {0};
long long re = 0;
long long ret[MAXN];

int getLCA(int a, int b) {
    if (dep[a] > dep[b]) return getLCA(b, a);
    for (int i = LOG - 1; i >= 0; i--) {
        if (par[b][i] != -1 && dep[par[b][i]] >= dep[a]) {
            b = par[b][i];
        }
    }
    if (a == b) return a;
    for (int i = LOG - 1; i >= 0; i--) {
        if (par[a][i] != par[b][i]) {
            a = par[a][i];
            b = par[b][i];
        }
    }
    return par[a][0];
}

void _add(int f, bool girl, int delta) {
    re -= 1ll * countGirl[f] * countBoy[f];
    if(girl) countGirl[f]+=delta; else countBoy[f] += delta;
    re += 1ll * countGirl[f] * countBoy[f];
}

void moAdd(int pos) {
    int id = path[pos];
    cnt[id] ^= 1;
    if(cnt[id] == 1) _add(f[id],isGirl[id], 1); else _add(f[id],isGirl[id],-1);
}

void moRemove(int pos) {
    int id = path[pos];
    if(cnt[id] == 1) _add(f[id],isGirl[id], -1); else _add(f[id],isGirl[id],1);
    cnt[id] ^= 1;
}

bool moDataCmp(const MoData& m1, const MoData& m2) {
    if(BL[m1.l] != BL[m2.l]) return BL[m1.l] < BL[m2.l]; else return m1.r < m2.r;

    // if((m1.l >> 9) != (m2.l>>9)) return m1.l < m2.l;
    // return m1.r < m2.r;
}
void dfs(int v, int p) {
    par[v][0] = p;
    if(p != -1) {
        dep[v] = dep[p] + 1;
    }

    st[v] = ++npath;
    path[npath ] = v;
    FR(i, g[v].size()) {
        int u = g[v][i];
        if(u != p) {
            dfs(u,v);
        }
    }

    en[v] = ++npath;
    path[npath] = v;
}

int main () {
    // ios_base::sync_with_stdio(false);
    // cin.tie(0);
    // cout.tie(0);
    //cin>>n;
    scanf("%d",&n);
    FR(i,n) {
        //cin>>val;
        scanf("%d",&val);
        isGirl[i] = (1 == val);
    }
    FR(i,n) {
        //cin>>f[i];
        scanf("%d",&f[i]);
        ff[i] = f[i];
    }
    sort(ff, ff + n);
    FR(i,n) f[i] = lower_bound(ff, ff + n, f[i]) - ff;

    FR(i,n - 1) {
        //cin>>from>>to;
        scanf("%d%d",&from,&to);
        from--; to --;
        g[from].push_back(to);
        g[to].push_back(from);
    }
    for (LOG = 1; (1 << LOG) < n; LOG++);
    dfs(0, -1);
    for(int j = 1; j < LOG;++j)
        for(int i = 0 ; i < n; ++i) {
            if(par[i][j-1] != -1) {
                par[i][j] = par[par[i][j-1]][j - 1];
            }
        }

    cin>>q;
    FR(i,q) {
        //cin>>from>>to;
        scanf("%d%d",&from,&to);
        from--;to--;
        if(st[from] > st[to]) swap(from,to);
        p = getLCA(from, to);
        mo[i].id = i;
        if(from == p) {
            mo[i].l = st[from];
            mo[i].r = st[to];
            mo[i].add = -1;
        } else {
            mo[i].l = en[from];
            mo[i].r = st[to];
            mo[i].add = p;
        }
    }

    blockSize = sqrt(npath) ;
    for(int i = 1 ; i<= npath; ++i) BL[i] = (i - 1)/blockSize + 1 ;
    sort(mo, mo + q, moDataCmp);
    int moStart = mo[0].l;
    int moEnd = moStart - 1;
    // FR(i,npath) cerr<<path[i]<<" ";
    // cerr<<endl;

    FR(i,q) {
        int l = mo[i].l;
        int r = mo[i].r;
        while(moStart < l) moRemove(moStart ++);
        while(moStart > l) moAdd(--moStart);
        while(moEnd < r) moAdd(++moEnd);
        while(moEnd > r) moRemove(moEnd--);
        if(mo[i].add == -1) {
            ret[mo[i].id] = re;
        } else {
            int p = mo[i].add;
            _add(f[p], isGirl[p], 1);
            ret[mo[i].id] = re;
            _add(f[p], isGirl[p], -1);
        }
    }

    FR(i,q) printf("%lld\n",ret[i]);

    return 0;
}