//#pragma GCC optimize("Ofast")
//#pragma GCC target("sse,sse2,sse3,ssse3,sse4")

#include <bits/stdc++.h>

#include <ext/pb_ds/assoc_container.hpp>
#include <ext/pb_ds/tree_policy.hpp>
#include <ext/pb_ds/detail/standard_policies.hpp>

#define pb push_back
#define F first
#define S second
#define lll long long
#define lld long double

using namespace std;
using namespace __gnu_pbds;

template <typename T>
using ordered_set = tree <T,null_type,less<T>,rb_tree_tag,tree_order_statistics_node_update>;

const int N = 1e5 + 229;
const lll M = 1e9 + 7;
const lll M2 = 1e9 + 9;
const int mod = 998244353;
const int rx[8] = {1, 1, -1, -1, -2, -2, 2, 2};
const int ry[8] = {-2, 2, -2, 2, 1, -1, 1, -1};
const lld eps = 1e-7;
const double pi = acos(-1.0);

bool who[N];

int f[N];

vector < int > g[N], way;

int tin[N], tout[N], up[N][20], timer = -1;

int k, kol[N];

int s, ans[N];

unordered_map < int, int > boy, girl;

struct node {
    int l, r, nom, lca;
    bool need;
    bool operator < (const node a) {
        if (l / k == a.l / k) {
            return r < a.r;
        }
        return l / k < a.l / k;
    }
};

vector < node > q;

void dfs(int v, int p = 0) {
    ++timer;
    tin[v] = timer;
    up[v][0] = p;
    way.pb(v);
    for (int i = 1; i < 20; ++i) {
        up[v][i] = up[up[v][i - 1]][i - 1];
    }
    for (auto to : g[v]) {
        if (to == p) {
            continue;
        }
        dfs(to, v);
    }
    way.pb(v);
    ++timer;
    tout[v] = timer;
}

bool upper(int a, int b) {
    return (tin[a] <= tin[b] && tout[a] >= tout[b]);
}

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

void add(int i) {
    int now = 0;
    int v = way[i];
    if (!who[v]) {
        now = girl[f[v]];
    } else {
        now = boy[f[v]];
    }
    ++kol[v];
    if (kol[v] == 1) {
        s += now;
        if (!who[v]) {
            ++boy[f[v]];
        } else {
            ++girl[f[v]];
        }
    } else {
        s -= now;
        if (!who[v]) {
            --boy[f[v]];
        } else {
            --girl[f[v]];
        }
    }
}

void del(int i) {
    int now = 0;
    int v = way[i];
    if (!who[v]) {
        now = girl[f[v]];
    } else {
        now = boy[f[v]];
    }
    --kol[v];
    if (kol[v] == 1) {
        s += now;
        if (!who[v]) {
            ++boy[f[v]];
        } else {
            ++girl[f[v]];
        }
    } else {
        s -= now;
        if (!who[v]) {
            --boy[f[v]];
        } else {
            --girl[f[v]];
        }
    }
}

int main() {
    ios_base::sync_with_stdio(0);
    cin.tie(0);
    cout.tie(0);
    srand(time(0));
#ifdef LOCAL
    freopen("input.txt", "r", stdin);
    freopen("output.txt", "w", stdout);
#else
//    freopen("input.txt", "r", stdin);
//    freopen("output.txt", "w", stdout);
#endif
    int n;
    cin >> n;
    for (int i = 0; i < n; ++i) {
        cin >> who[i];
    }
    for (int i = 0; i < n; ++i) {
        cin >> f[i];
    }
    int x, y;
    for (int i = 1; i < n; ++i) {
        cin >> x >> y;
        --x;
        --y;
        g[x].pb(y);
        g[y].pb(x);
    }
    dfs(0);
    int m;
    node now;
    cin >> m;
    for (int i = 0; i < m; ++i) {
        cin >> x >> y;
        --x;
        --y;
        now.nom = i;
        now.need = 0;
        now.lca = lca(x, y);
        if (tin[x] > tin[y]) {
            swap(x, y);
        }
        if (upper(x, y)) {
            now.l = tin[x];
            now.r = tin[y];
            now.need = 0;
        } else {
            now.l = tout[x];
            now.r = tin[y];
            now.need = 1;
        }
        q.pb(now);
    }
//    for (auto i : way) {
//        cout << i + 1 << ' ';
//    }
//    cout << endl;
    k = sqrt(int(q.size()));
    sort(q.begin(), q.end());
    int l = 0, r = -1;
    for (auto i : q) {
//        cout << i.l << ' ' << i.r << endl;
        while (r < i.r) {
            ++r;
            add(r);
        }
        while (l > i.l) {
            --l;
            add(l);
        }
        while (r > i.r) {
            del(r);
            --r;
        }
        while (l < i.l) {
            del(l);
            ++l;
        }
//        cout << girl[9] << endl;
        if (i.need) {
            int v = i.lca;
            if (!who[v]) {
                ans[i.nom] += girl[f[v]];
            } else {
                ans[i.nom] += boy[f[v]];
            }
        }
        ans[i.nom] += s;
    }
    for (int i = 0; i < m; ++i) {
        cout << ans[i] << '\n';
    }
    return 0;
}


//#pragma GCC optimize("Ofast")
//#pragma GCC target("sse,sse2,sse3,ssse3,sse4")

#include <bits/stdc++.h>

#include <ext/pb_ds/assoc_container.hpp>
#include <ext/pb_ds/tree_policy.hpp>
#include <ext/pb_ds/detail/standard_policies.hpp>

#define pb push_back
#define F first
#define S second
#define lll long long
#define lld long double

using namespace std;
using namespace __gnu_pbds;

template <typename T>
using ordered_set = tree <T,null_type,less<T>,rb_tree_tag,tree_order_statistics_node_update>;

const int N = 1e5 + 229;
const lll M = 1e9 + 7;
const lll M2 = 1e9 + 9;
const int mod = 998244353;
const int rx[8] = {1, 1, -1, -1, -2, -2, 2, 2};
const int ry[8] = {-2, 2, -2, 2, 1, -1, 1, -1};
const lld eps = 1e-7;
const double pi = acos(-1.0);

bool who[N];

int f[N];

vector < int > g[N], way;

int tin[N], tout[N], up[N][20], timer = -1;

int k, kol[N];

lll s, ans[N];

unordered_map < int, lll > boy, girl;

struct node {
    int l, r, nom, lca;
    bool need;
    bool operator < (const node a) {
        if (l / k == a.l / k) {
            return r < a.r;
        }
        return l / k < a.l / k;
    }
};

vector < node > q;

void dfs(int v, int p = 0) {
    ++timer;
    tin[v] = timer;
    up[v][0] = p;
    way.pb(v);
    for (int i = 1; i < 20; ++i) {
        up[v][i] = up[up[v][i - 1]][i - 1];
    }
    for (auto to : g[v]) {
        if (to == p) {
            continue;
        }
        dfs(to, v);
    }
    way.pb(v);
    ++timer;
    tout[v] = timer;
}

bool upper(int a, int b) {
    return (tin[a] <= tin[b] && tout[a] >= tout[b]);
}

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

void add(int i) {
    lll now = 0;
    int v = way[i];
    if (!who[v]) {
        now = girl[f[v]];
    } else {
        now = boy[f[v]];
    }
    ++kol[v];
    if (kol[v] == 1) {
        s += now;
        if (!who[v]) {
            ++boy[f[v]];
        } else {
            ++girl[f[v]];
        }
    } else {
        s -= now;
        if (!who[v]) {
            --boy[f[v]];
        } else {
            --girl[f[v]];
        }
    }
}

void del(int i) {
    lll now = 0;
    int v = way[i];
    if (!who[v]) {
        now = girl[f[v]];
    } else {
        now = boy[f[v]];
    }
    --kol[v];
    if (kol[v] == 1) {
        s += now;
        if (!who[v]) {
            ++boy[f[v]];
        } else {
            ++girl[f[v]];
        }
    } else {
        s -= now;
        if (!who[v]) {
            --boy[f[v]];
        } else {
            --girl[f[v]];
        }
    }
}

int main() {
    ios_base::sync_with_stdio(0);
    cin.tie(0);
    cout.tie(0);
    srand(time(0));
#ifdef LOCAL
    freopen("input.txt", "r", stdin);
    freopen("output.txt", "w", stdout);
#else
//    freopen("input.txt", "r", stdin);
//    freopen("output.txt", "w", stdout);
#endif
    int n;
    cin >> n;
    for (int i = 0; i < n; ++i) {
        cin >> who[i];
    }
    for (int i = 0; i < n; ++i) {
        cin >> f[i];
    }
    int x, y;
    for (int i = 1; i < n; ++i) {
        cin >> x >> y;
        --x;
        --y;
        g[x].pb(y);
        g[y].pb(x);
    }
    dfs(0);
    int m;
    node now;
    cin >> m;
    for (int i = 0; i < m; ++i) {
        cin >> x >> y;
        --x;
        --y;
        now.nom = i;
        now.need = 0;
        now.lca = lca(x, y);
        if (tin[x] > tin[y]) {
            swap(x, y);
        }
        if (upper(x, y)) {
            now.l = tin[x];
            now.r = tin[y];
            now.need = 0;
        } else {
            now.l = tout[x];
            now.r = tin[y];
            now.need = 1;
        }
        q.pb(now);
    }
//    for (auto i : way) {
//        cout << i + 1 << ' ';
//    }
//    cout << endl;
    k = sqrt(int(q.size()));
    sort(q.begin(), q.end());
    int l = 0, r = -1;
    for (auto i : q) {
//        cout << i.l << ' ' << i.r << endl;
        while (r < i.r) {
            ++r;
            add(r);
        }
        while (l > i.l) {
            --l;
            add(l);
        }
        while (r > i.r) {
            del(r);
            --r;
        }
        while (l < i.l) {
            del(l);
            ++l;
        }
//        cout << girl[9] << endl;
        if (i.need) {
            int v = i.lca;
            if (!who[v]) {
                ans[i.nom] += girl[f[v]];
            } else {
                ans[i.nom] += boy[f[v]];
            }
        }
        ans[i.nom] += s;
    }
    for (int i = 0; i < m; ++i) {
        cout << ans[i] << '\n';
    }
    return 0;
}


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

const int MAX_N = 1e5 + 5, LOG_MAX_N = 18, MAX_M = 1e5 + 5;

struct Node {
	static int nextInOrder;

	bool vis, isBoy;
	int value, in, out;
	Node *ancs[LOG_MAX_N];
	vector< Node * > edges;

	Node() {
		for(int i = 0; i < LOG_MAX_N; i++) {
			ancs[i] = nullptr;
		}
		edges.clear();
	}

	void Dfs() {
		vis = true;
		in = nextInOrder++;

		for(Node *v : edges) {
			if(v -> vis) {
				ancs[0] = v;
				continue;
			}

			v -> Dfs();
		}

		out = nextInOrder++;
	}
};

struct Query {
	int low, high, additional, ind;
	ll ans;

	Query(int low = 0, int high = 0, int additional = 0, int ind = 0) : low(low), high(high), additional(additional), ind(ind) {

	}

	struct SortUnsolved {
		int blockSize;

		SortUnsolved(int blockSize = 1) : blockSize(blockSize) {

		}

		bool operator() (const Query &x, const Query &y) const {
			int blockX = x.low / blockSize, blockY = y.low / blockSize;

			if(blockX != blockY) {
				return blockX < blockY;
			}
			else {
				return x.high < y.high;
			}
		}
	};

	struct SortSolved {
		bool operator() (const Query &x, const Query &y) const {
			return x.ind < y.ind;
		}
	};
};

int Node::nextInOrder = 1;

bool usedNodes[MAX_N];
int n, dfsOrder[2 * MAX_N], m, cntBoysWithValue[MAX_N], cntGirlsWithValue[MAX_N];
Node tree[MAX_N];
Query qs[MAX_M];

void CompressValues() {
	set< int > uniqueValues;

	for(int i = 1; i <= n; i++) {
		uniqueValues.insert(tree[i].value);
	}

	unordered_map< int, int > compressedValues;

	int compressedValue = 1;
	for(int val : uniqueValues) {
		compressedValues[val] = compressedValue++;
	}

	for(int i = 1; i <= n; i++) {
		tree[i].value = compressedValues[tree[i].value];
	}
}

void PrecomputeAncestors() {
	for(int j = 1; j < LOG_MAX_N; j++) {
		for(int i = 1; i <= n; i++) {
			if(tree[i].ancs[j - 1] != nullptr) {
				tree[i].ancs[j] = tree[i].ancs[j - 1] -> ancs[j - 1];
			}
		}
	}
}

bool IsUpper(Node *x, Node *y) {
	return (x -> in <= y -> in && y -> out <= x -> out);
}

Node *FindLca(Node *x, Node *y) {
	if(IsUpper(x, y)) {
		return x;
	}
	else if(IsUpper(y, x)) {
		return y;
	}

	for(int j = LOG_MAX_N - 1; j >= 0; j--) {
		if(x -> ancs[j] != nullptr && !IsUpper(x -> ancs[j], y)) {
			x = x -> ancs[j];
		}
	}

	return x -> ancs[0];
}

int AddOrRemove(int ind) {
	Node *node = &tree[dfsOrder[ind]];
	int currAns = 0;

	if(usedNodes[dfsOrder[ind]]) {
		if(node -> isBoy) {
			currAns -= cntGirlsWithValue[node -> value];
			cntBoysWithValue[node -> value]--;
		}
		else {
			currAns -= cntBoysWithValue[node -> value];
			cntGirlsWithValue[node -> value]--;
		}
	}
	else {
		if(node -> isBoy) {
			currAns += cntGirlsWithValue[node -> value];
			cntBoysWithValue[node -> value]++;
		}
		else {
			currAns += cntBoysWithValue[node -> value];
			cntGirlsWithValue[node -> value]++;
		}
	}

	usedNodes[dfsOrder[ind]] = !usedNodes[dfsOrder[ind]];

	return currAns;
}

void ComputeAnswers() {
	int low = qs[0].low, high = qs[0].low - 1;
	ll currAns = 0;

	for(int i = 0; i < m; i++) {
		while(high < qs[i].high) {
			high++;
			currAns += 1ll * AddOrRemove(high);
		}

		while(high > qs[i].high) {
			currAns += 1ll * AddOrRemove(high);
			high--;
		}

		while(low > qs[i].low) {
			low--;
			currAns += 1ll * AddOrRemove(low);
		}

		while(low < qs[i].low) {
			currAns += 1ll * AddOrRemove(low);
			low++;
		}

		qs[i].ans = currAns;

		if(qs[i].additional != -1) {
			Node *node = &tree[dfsOrder[qs[i].additional]];

			if(node -> isBoy) {
				qs[i].ans += cntGirlsWithValue[node -> value];
			}
			else {
				qs[i].ans += cntBoysWithValue[node -> value];
			}
		}
	}
}

int main() {
	scanf(" %d", &n);

	for(int i = 1; i <= n; i++) {
		scanf(" %d", &tree[i].isBoy);
	}

	for(int i = 1; i <= n; i++) {
		scanf(" %d", &tree[i].value);
	}

	CompressValues();

	for(int i = 0; i < n - 1; i++) {
		int u, v;
		scanf(" %d %d", &u, &v);

		tree[u].edges.pb(&tree[v]);
		tree[v].edges.pb(&tree[u]);
	}

	tree[1].Dfs();
	PrecomputeAncestors();

	for(int i = 1; i <= n; i++) {
		dfsOrder[tree[i].in] = i;
		dfsOrder[tree[i].out] = i;
	}

	scanf(" %d", &m);

	for(int i = 0; i < m; i++) {
		int u, v;
		scanf(" %d %d", &u, &v);

		if(tree[u].in > tree[v].in) {
			swap(u, v);
		}

		Node *lca = FindLca(&tree[u], &tree[v]);

		if(&tree[u] == lca) {
			qs[i] = Query(tree[u].in, tree[v].in, -1, i);
		}
		else {
			qs[i] = Query(tree[u].out, tree[v].in, lca -> in, i);
		}
	}

	sort(qs, qs + m, Query::SortUnsolved(sqrt(n)));
	ComputeAnswers();
	sort(qs, qs + m, Query::SortSolved());

	for(int i = 0; i < m; i++) {
		printf("%lld\n", qs[i].ans);
	}

	return 0;
}


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

const int MAX_N = 1e5 + 5, LOG_MAX_N = 18, MAX_M = 1e5 + 5;

struct Node {
	static int nextInOrder;

	bool vis, isBoy;
	int value, in, out;
	Node *ancs[LOG_MAX_N];
	vector< Node * > edges;

	Node() {
		for(int i = 0; i < LOG_MAX_N; i++) {
			ancs[i] = nullptr;
		}
		edges.clear();
	}

	void Dfs() {
		vis = true;
		in = nextInOrder++;

		for(Node *v : edges) {
			if(v -> vis) {
				ancs[0] = v;
				continue;
			}

			v -> Dfs();
		}

		out = nextInOrder++;
	}
};

struct Query {
	int low, high, additional, ind;
	ll ans;

	Query(int low = 0, int high = 0, int additional = 0, int ind = 0) : low(low), high(high), additional(additional), ind(ind) {

	}

	struct SortUnsolved {
		int blockSize;

		SortUnsolved(int blockSize = 1) : blockSize(blockSize) {

		}

		bool operator() (const Query &x, const Query &y) const {
			int blockX = x.low / blockSize, blockY = y.low / blockSize;

			if(blockX != blockY) {
				return blockX < blockY;
			}
			else {
				return x.high < y.high;
			}
		}
	};

	struct SortSolved {
		bool operator() (const Query &x, const Query &y) const {
			return x.ind < y.ind;
		}
	};
};

int Node::nextInOrder = 1;

bool usedNodes[MAX_N];
int n, dfsOrder[2 * MAX_N], m, cntBoysWithValue[MAX_N], cntGirlsWithValue[MAX_N];
Node tree[MAX_N];
Query qs[MAX_M];

void CompressValues() {
	set< int > uniqueValues;

	for(int i = 1; i <= n; i++) {
		uniqueValues.insert(tree[i].value);
	}

	unordered_map< int, int > compressedValues;

	int compressedValue = 1;
	for(int val : uniqueValues) {
		compressedValues[val] = compressedValue++;
	}

	for(int i = 1; i <= n; i++) {
		tree[i].value = compressedValues[tree[i].value];
	}
}

void PrecomputeAncestors() {
	for(int j = 1; j < LOG_MAX_N; j++) {
		for(int i = 1; i <= n; i++) {
			if(tree[i].ancs[j - 1] != nullptr) {
				tree[i].ancs[j] = tree[i].ancs[j - 1] -> ancs[j - 1];
			}
		}
	}
}

bool IsUpper(Node *x, Node *y) {
	return (x -> in <= y -> in && y -> out <= x -> out);
}

Node *FindLca(Node *x, Node *y) {
	if(IsUpper(x, y)) {
		return x;
	}
	else if(IsUpper(y, x)) {
		return y;
	}

	for(int j = LOG_MAX_N - 1; j >= 0; j--) {
		if(x -> ancs[j] != nullptr && !IsUpper(x -> ancs[j], y)) {
			x = x -> ancs[j];
		}
	}

	return x -> ancs[0];
}

int AddOrRemove(int ind) {
	Node *node = &tree[dfsOrder[ind]];
	int currAns = 0;

	if(usedNodes[dfsOrder[ind]]) {
		if(node -> isBoy) {
			currAns -= cntGirlsWithValue[node -> value];
			cntBoysWithValue[node -> value]--;
		}
		else {
			currAns -= cntBoysWithValue[node -> value];
			cntGirlsWithValue[node -> value]--;
		}
	}
	else {
		if(node -> isBoy) {
			currAns += cntGirlsWithValue[node -> value];
			cntBoysWithValue[node -> value]++;
		}
		else {
			currAns += cntBoysWithValue[node -> value];
			cntGirlsWithValue[node -> value]++;
		}
	}

	usedNodes[dfsOrder[ind]] = !usedNodes[dfsOrder[ind]];

	return currAns;
}

void ComputeAnswers() {
	int low = qs[0].low, high = qs[0].low - 1;
	ll currAns = 0;

	for(int i = 0; i < m; i++) {
		while(high < qs[i].high) {
			high++;
			currAns += 1ll * AddOrRemove(high);
		}

		while(high > qs[i].high) {
			currAns += 1ll * AddOrRemove(high);
			high--;
		}

		while(low > qs[i].low) {
			low--;
			currAns += 1ll * AddOrRemove(low);
		}

		while(low < qs[i].low) {
			currAns += 1ll * AddOrRemove(low);
			low++;
		}

		qs[i].ans = currAns;

		if(qs[i].additional != -1) {
			Node *node = &tree[dfsOrder[qs[i].additional]];

			if(node -> isBoy) {
				qs[i].ans += cntGirlsWithValue[node -> value];
			}
			else {
				qs[i].ans += cntBoysWithValue[node -> value];
			}
		}
	}
}

int main() {
	scanf(" %d", &n);

	for(int i = 1; i <= n; i++) {
		scanf(" %d", &tree[i].isBoy);
	}

	for(int i = 1; i <= n; i++) {
		scanf(" %d", &tree[i].value);
	}

	CompressValues();

	for(int i = 0; i < n - 1; i++) {
		int u, v;
		scanf(" %d %d", &u, &v);

		tree[u].edges.pb(&tree[v]);
		tree[v].edges.pb(&tree[u]);
	}

	tree[1].Dfs();
	PrecomputeAncestors();

	for(int i = 1; i <= n; i++) {
		dfsOrder[tree[i].in] = i;
		dfsOrder[tree[i].out] = i;
	}

	scanf(" %d", &m);

	for(int i = 0; i < m; i++) {
		int u, v;
		scanf(" %d %d", &u, &v);

		if(tree[u].in > tree[v].in) {
			swap(u, v);
		}

		Node *lca = FindLca(&tree[u], &tree[v]);

		if(&tree[u] == lca) {
			qs[i] = Query(tree[u].in, tree[v].in, -1, i);
		}
		else {
			qs[i] = Query(tree[u].out, tree[v].in, lca -> in, i);
		}
	}

	sort(qs, qs + m, Query::SortUnsolved(2 * sqrt(n)));
	ComputeAnswers();
	sort(qs, qs + m, Query::SortSolved());

	for(int i = 0; i < m; i++) {
		printf("%lld\n", qs[i].ans);
	}

	return 0;
}


#include<stdio.h>
#include<iostream>
#include<string.h>
#include<string>
#include<ctype.h>
#include<math.h>
#include<set>
#include<map>
#include<vector>
#include<queue>
#include<bitset>
#include<algorithm>
#include<time.h>
using namespace std;
void fre() { freopen("c://test//input.in", "r", stdin); freopen("c://test//output.out", "w", stdout); }
#define MS(x, y) memset(x, y, sizeof(x))
#define ls o<<1
#define rs o<<1|1
typedef long long LL;
typedef unsigned long long UL;
typedef unsigned int UI;
template <class T1, class T2>inline void gmax(T1 &a, T2 b) { if (b > a)a = b; }
template <class T1, class T2>inline void gmin(T1 &a, T2 b) { if (b < a)a = b; }
const int N = 1e5 + 10, M = 0, Z = 1e9 + 7, inf = 0x3f3f3f3f;
template <class T1, class T2>inline void gadd(T1 &a, T2 b) { a = (a + b) % Z; }
int casenum, casei;
int v[N];
int blk[N], blkid;
bool way[N];
int cnt[2][N];
int SZ;
int is[N];
int in[N], out[N], tim;
int c[N], h[N];
int sta[N], top;
int ans[N];
vector<int>a[N];
int fa[N], d[N];
int n, m;
struct Q
{
    int l, r, o;
    bool operator < (const Q & b)const
    {
        if(blk[l] != blk[b.l])return blk[l] < blk[b.l];
        return in[r] < in[b.r];
    }
}q[N];
int dfs(int x)
{
    in[x] = ++tim;
    is[tim] = x;
    int sz = 0;
    for(auto y : a[x])if(y != fa[x])
    {
        fa[y] = x;
        d[y] = d[x] + 1;
        sz += dfs(y);
        if(sz >= SZ)
        {
            ++blkid;
            while(sz--)blk[sta[top--]] = blkid;
        }
    }
    sta[++top] = x;
    out[x] = tim;
    return sz + 1;
}
int ANS;
void ins(int x)
{
    int t = v[x];
    ANS += cnt[t ^ 1][c[x]];
    ++cnt[t][c[x]];
}
void del(int x)
{
    int t = v[x];
    ANS -= cnt[t ^ 1][c[x]];
    --cnt[t][c[x]];
}
void inv(int x)
{
    if(way[x])del(x);
    else ins(x);
    way[x] ^= 1;
}
int cross;
void moveup(int &x)
{
    if(!cross)
    {
        if(way[x] && !way[fa[x]])cross = x;
        if(!way[x] && way[fa[x]])cross = fa[x];
    }
    inv(x);
    x = fa[x];
}
void mov(int x, int y)
{
    if(x == y)return;
    cross = 0;
    if(way[y])cross = y;
    while(d[x] > d[y])moveup(x);
    while(d[y] > d[x])moveup(y);
    while(x != y)moveup(x), moveup(y);
    inv(x);
    inv(cross);
}
int main()
{
	while(~scanf("%d", &n))
	{
	    SZ = sqrt(n / 10);
        for(int i = 1; i <= n; ++i)
        {
            scanf("%d", &v[i]);
            a[i].clear();
            way[i] = 0;
            cnt[0][i] = cnt[1][i] = 0;
        }
        for(int i = 1; i <= n; ++i)
        {
            scanf("%d", &c[i]);
            h[i] = c[i];
        }
        sort(h + 1, h+ n + 1); int hh = unique(h + 1, h + n + 1) - h - 1;
        for(int i = 1; i <= n; ++i)
        {
            c[i] = lower_bound(h + 1, h + hh + 1, c[i]) - h;
        }
        for(int i = 1; i < n; ++i)
        {
            int x, y; scanf("%d%d", &x, &y);
            a[x].push_back(y);
            a[y].push_back(x);

        }
        tim = blkid = 0;
        fa[1] = d[1] = 0;
        dfs(1);
        ++blkid; while(top)blk[sta[top--]] = blkid;
        scanf("%d", &m);
        for(int i = 1; i <= m; ++i)
        {
            int x, y; scanf("%d%d", &x, &y);
            q[i] = {x, y, i};
        }
        sort(q + 1, q + m + 1);

        int l = 1, r = 1;
        ANS = 0;
        ins(1); way[1] = 1;
        for(int i = 1; i <= m; ++i)
        {
            mov(l, q[i].l); l = q[i].l;
            mov(r, q[i].r); r = q[i].r;
            ans[q[i].o] = ANS;
        }
        for(int i = 1; i <= m; ++i)
        {
            printf("%d\n", ans[i]);
        }
	}

	return 0;
}
/*
【trick&&吐槽】

【题意】

【分析】

【时间复杂度&&优化】

*/


#include<stdio.h>
#include<iostream>
#include<string.h>
#include<string>
#include<ctype.h>
#include<math.h>
#include<set>
#include<map>
#include<vector>
#include<queue>
#include<bitset>
#include<algorithm>
#include<time.h>
using namespace std;
void fre() { freopen("c://test//input.in", "r", stdin); freopen("c://test//output.out", "w", stdout); }
#define MS(x, y) memset(x, y, sizeof(x))
#define ls o<<1
#define rs o<<1|1
typedef long long LL;
typedef unsigned long long UL;
typedef unsigned int UI;
template <class T1, class T2>inline void gmax(T1 &a, T2 b) { if (b > a)a = b; }
template <class T1, class T2>inline void gmin(T1 &a, T2 b) { if (b < a)a = b; }
const int N = 1e5 + 10, M = 0, Z = 1e9 + 7, inf = 0x3f3f3f3f;
template <class T1, class T2>inline void gadd(T1 &a, T2 b) { a = (a + b) % Z; }
int casenum, casei;
int v[N];
int blk[N], blkid;
bool way[N];
int cnt[2][N];
int SZ;
int is[N];
int in[N], out[N], tim;
int c[N], h[N];
int sta[N], top;
UI ans[N];
vector<int>a[N];
int fa[N], d[N];
int n, m;
struct Q
{
    int l, r, o;
    bool operator < (const Q & b)const
    {
        if(blk[l] != blk[b.l])return blk[l] < blk[b.l];
        return in[r] < in[b.r];
    }
}q[N];
int dfs(int x)
{
    in[x] = ++tim;
    is[tim] = x;
    int sz = 0;
    for(auto y : a[x])if(y != fa[x])
    {
        fa[y] = x;
        d[y] = d[x] + 1;
        sz += dfs(y);
        if(sz >= SZ)
        {
            ++blkid;
            while(sz--)blk[sta[top--]] = blkid;
        }
    }
    sta[++top] = x;
    out[x] = tim;
    return sz + 1;
}
UI ANS;
void ins(int x)
{
    int t = v[x];
    ANS += cnt[t ^ 1][c[x]];
    ++cnt[t][c[x]];
}
void del(int x)
{
    int t = v[x];
    ANS -= cnt[t ^ 1][c[x]];
    --cnt[t][c[x]];
}
void inv(int x)
{
    if(way[x])del(x);
    else ins(x);
    way[x] ^= 1;
}
int cross;
void moveup(int &x)
{
    if(!cross)
    {
        if(way[x] && !way[fa[x]])cross = x;
        if(!way[x] && way[fa[x]])cross = fa[x];
    }
    inv(x);
    x = fa[x];
}
void mov(int x, int y)
{
    if(x == y)return;
    cross = 0;
    if(way[y])cross = y;
    while(d[x] > d[y])moveup(x);
    while(d[y] > d[x])moveup(y);
    while(x != y)moveup(x), moveup(y);
    inv(x);
    inv(cross);
}
const int SIZE = 1 << 20;
char S[SIZE], *SS = S, *ST = S, CH;
inline char getc()
{
	return SS == ST && (ST = (SS = S) + fread(S, 1, SIZE, stdin), SS == ST) ? 0 : *SS++;
}
template<class T>inline bool read(T &x)
{
	x = 0; int sgn = 1;
	while (CH = getc(), !isdigit(CH) && CH != '-')if (CH == 0)return 0;
	if (CH == '-')sgn = -1; else x = CH ^ 48;
	while (CH = getc(), isdigit(CH))x = (x << 3) + (x << 1) + (CH ^ 48);
	x *= sgn;
	return 1;
}
int main()
{
	//while(~scanf("%d", &n))
	while(read(n))
	{
	    SZ = sqrt(n);
        for(int i = 1; i <= n; ++i)
        {
            //scanf("%d", &v[i]);
            read(v[i]);
            /*a[i].clear();
            way[i] = 0;
            cnt[0][i] = cnt[1][i] = 0;
            */
        }
        for(int i = 1; i <= n; ++i)
        {
            //scanf("%d", &c[i]);
            read(c[i]);
            h[i] = c[i];
        }
        sort(h + 1, h+ n + 1); int hh = unique(h + 1, h + n + 1) - h - 1;
        for(int i = 1; i <= n; ++i)
        {
            c[i] = lower_bound(h + 1, h + hh + 1, c[i]) - h;
        }
        for(int i = 1; i < n; ++i)
        {
            int x, y;
            //scanf("%d%d", &x, &y);
            read(x); read(y);
            a[x].push_back(y);
            a[y].push_back(x);

        }
        tim = blkid = 0;
        fa[1] = d[1] = 0;
        dfs(1);
        ++blkid; while(top)blk[sta[top--]] = blkid;
        //scanf("%d", &m);
        read(m);
        for(int i = 1; i <= m; ++i)
        {
            int x, y;
            //scanf("%d%d", &x, &y);
            read(x); read(y);
            q[i] = {x, y, i};
        }
        sort(q + 1, q + m + 1);

        int l = 1, r = 1;
        ANS = 0;
        ins(1); way[1] = 1;
        for(int i = 1; i <= m; ++i)
        {
            mov(l, q[i].l); l = q[i].l;
            mov(r, q[i].r); r = q[i].r;
            ans[q[i].o] = ANS;
        }
        for(int i = 1; i <= m; ++i)
        {
            printf("%u\n", ans[i]);
        }
	}

	return 0;
}
/*
【trick&&吐槽】

【题意】

【分析】

【时间复杂度&&优化】

*/


#include<stdio.h>
#include<math.h>
#include<string.h>
#include<iostream>
#include<algorithm>
#include<vector>
using namespace std;
typedef long long ll;
const int MAXN =100010;
int n,m;
vector<int>v;
struct edge{
	int to,nxt;
}ed[MAXN<<1];
int head[MAXN],cnt;
int dfn[MAXN],f[MAXN][20],dep[MAXN],pos,dfnx,p[MAXN<<1],L[MAXN],R[MAXN],vis[MAXN],vl[MAXN],aa[MAXN];
int fv[MAXN],a[MAXN];
void addedge(int u,int v){
	ed[cnt].to=v;
	ed[cnt].nxt=head[u];
	head[u]=cnt++;
}
void dfs(int u)
{
	int i;
	dfn[u]=++dfnx;
	vl[dfn[u]]=fv[u];
	aa[dfn[u]]=a[u];
	p[++pos]=dfn[u];
    L[u]=pos;
	for(i=head[u];i!=-1;i=ed[i].nxt)  {
		if (!dep[ed[i].to]){
			dep[ed[i].to] = dep[u]+1;
			f[ed[i].to][0] = u;
			dfs(ed[i].to);
		}
	}
	p[++pos]=dfn[u];
	R[u]=pos;
}
int lca(int a,int b){
    int t,i;
    if(dep[a]<dep[b])swap(a,b);
    for(i=16;i>=0;i--){
        if(dep[f[a][i]]>=dep[b])a=f[a][i];
    }
    if(a==b)return a;
    for(i=16;i>=0;i--){
        if(f[a][i]!=f[b][i])a=f[a][i],b=f[b][i];
    }
    return f[a][0];
}
struct node{
	int	l,r,fa,idx;
	node(){}node(int _l,int _r,int _fa,int _idx){
		l=_l;r=_r;fa=_fa;idx=_idx;
	}
}qu[100010];
int len;
ll ans[100010];
bool cmp(const node &a,const node &b){
	if(a.l/len==b.l/len)return a.r<b.r;
	return a.l<b.l;
}
int mark[MAXN][2];
void work(){
	int l=qu[1].l,r=qu[1].l-1;
	ll step=0;
	for(int i=1;i<=m;i++){
		int ml=qu[i].l,mr=qu[i].r;
		while(l<ml){
			vis[p[l]]^=1;
			if(vis[p[l]]){
				mark[vl[p[l]]][aa[p[l]]]++;
				step+=mark[vl[p[l]]][aa[p[l]]^1];
			}
			else {
				mark[vl[p[l]]][aa[p[l]]]--;
				step-=mark[vl[p[l]]][aa[p[l]]^1];
			}
			l++;
		}
		while(l>ml){
			l--;
			vis[p[l]]^=1;
			if(vis[p[l]]){
				mark[vl[p[l]]][aa[p[l]]]++;
				step+=mark[vl[p[l]]][aa[p[l]]^1];
			}
			else {
				mark[vl[p[l]]][aa[p[l]]]--;
				step-=mark[vl[p[l]]][aa[p[l]]^1];
			}

		}
		while(r>mr){
			vis[p[r]]^=1;
			if(vis[p[r]]){
				mark[vl[p[r]]][aa[p[r]]]++;
				step+=mark[vl[p[r]]][aa[p[r]]^1];
			}
			else {
				mark[vl[p[r]]][aa[p[r]]]--;
				step-=mark[vl[p[r]]][aa[p[r]]^1];
			}
			r--;
		}
		while(r<mr){
			r++;
			vis[p[r]]^=1;
			if(vis[p[r]]){
				mark[vl[p[r]]][aa[p[r]]]++;
				step+=mark[vl[p[r]]][aa[p[r]]^1];
			}
			else {
				mark[vl[p[r]]][aa[p[r]]]--;
				step-=mark[vl[p[r]]][aa[p[r]]^1];
			}
		}
		ans[qu[i].idx]=step;
		if(qu[i].fa!=0){
			ans[qu[i].idx]+=mark[fv[qu[i].fa]][a[qu[i].fa]^1];
		}
	}
}

int main()
{
	memset(head,-1,sizeof(head));
	scanf("%d",&n);
	len=(int)sqrt(2*n);
	for(int i=1;i<=n;i++)scanf("%d",&a[i]);
	for(int i=1;i<=n;i++)scanf("%d",&fv[i]),v.push_back(fv[i]);
	sort(v.begin(),v.end());
	v.erase(unique(v.begin(),v.end()),v.end());
	for(int i=1;i<=n;i++)fv[i]=lower_bound(v.begin(),v.end(),fv[i])-v.begin()+1;
	for(int i=1;i<n;i++){
		int u,v;
		scanf("%d%d",&u,&v);
		addedge(u,v);
		addedge(v,u);
	}
	dep[1]=1;
	dfs(1);
	for(int j=1;(1<<j)<=n;j++){
    	for(int i=1;i<=n;i++){
    		f[i][j]=f[f[i][j-1]][j-1];
		}
	}
	scanf("%d",&m);
	for(int i=1;i<=m;i++){
		int u,v;
		scanf("%d%d",&u,&v);
		int LCA=lca(u,v);
		if(dfn[u]>dfn[v])swap(u,v);
		if(LCA==u){
			qu[i]=node(L[u],L[v],0,i);
		}
		else {
			qu[i]=node(R[u],L[v],LCA,i);
		}
	}
	sort(qu+1,qu+1+m,cmp);
	work();
	for(int i=1;i<=m;i++)printf("%lld\n",ans[i]);
	return 0;
}


#include<vector>
#include<math.h>
#include<stdio.h>
#include<string.h>
#include<iostream>
#include<algorithm>
using namespace std;
typedef long long ll;
const int MAXN=(int)1e5+10;
struct edge{
	int to,nxt;
}ed[MAXN<<1];
int head[MAXN],cnt;
int f[MAXN][20],dep[MAXN];
void addedge(int u,int v){
	ed[cnt].to=v;
	ed[cnt].nxt=head[u];
	head[u]=cnt++;
}
vector<int>ve;
int a[MAXN],vl[MAXN];
int L[MAXN],R[MAXN],p[MAXN<<1],pos;
void dfs(int u){
	p[++pos]=u;
	L[u]=pos;
	for(int i=head[u];i!=-1;i=ed[i].nxt){
		int v=ed[i].to;
		if(!dep[v]){
			f[v][0]=u;
			dep[v]=dep[u]+1;
			dfs(v);
		}
	}
	p[++pos]=u;
	R[u]=pos;
}
int lca(int u,int v){
	if(dep[u]<dep[v])swap(u,v);
	for(int i=16;i>=0;i--){
		if(dep[f[u][i]]>=dep[v])u=f[u][i];
	}
	if(u==v)return u;
	for(int i=16;i>=0;i--){
		if(f[u][i]!=f[v][i])u=f[u][i],v=f[v][i];
	}
	return f[u][0];
}
struct node{
	int l,r,fa,idx;
	node(){}node(int _l,int _r,int _fa,int _idx){
		l=_l;r=_r;fa=_fa;idx=_idx;
	}
}qu[MAXN];
int len;
bool cmp(const node &a,const node &b){
	if(a.l/len==b.l/len)return a.r<b.r;
	else return a.l<b.l;
}
ll ans[MAXN];int vis[MAXN],mark[MAXN][2];
void ban(int x,ll &y){
	x=p[x];
	vis[x]^=1;
	if(vis[x]){
		mark[vl[x]][a[x]]++;
		y+=mark[vl[x]][a[x]^1];
	}
	else {
		mark[vl[x]][a[x]]--;
		y-=mark[vl[x]][a[x]^1];
	}
}
void work(int m){
	int l,r;ll step=0;
	sort(qu+1,qu+1+m,cmp);
	l=qu[1].l,r=qu[1].l-1;
	for(int i=1;i<=m;i++){
		int ml,mr,idx,fa;
		ml=qu[i].l,mr=qu[i].r,idx=qu[i].idx,fa=qu[i].fa;
		while(l>ml)ban(--l,step);
		while(r<mr)ban(++r,step);
		while(l<ml)ban(l++,step);
		while(r>mr)ban(r--,step);
		ans[idx]=step;
		if(fa)ans[idx]+=mark[vl[fa]][a[fa]^1];
	}
}
int main()
{
	memset(head,-1,sizeof(head));
	int n;
	scanf("%d",&n);
	len=(int)sqrt(n+n);
	for(int i=1;i<=n;i++)scanf("%d",&a[i]);
	for(int i=1;i<=n;i++)scanf("%d",&vl[i]),ve.push_back(vl[i]);
	sort(ve.begin(),ve.end());ve.erase(unique(ve.begin(),ve.end()),ve.end());
	for(int i=1;i<=n;i++)vl[i]=lower_bound(ve.begin(),ve.end(),vl[i])-ve.begin()+1;
	for(int i=1;i<n;i++){
		int u,v;
		scanf("%d%d",&u,&v);
		addedge(u,v);
		addedge(v,u);
	}
	dep[1]=1;
	dfs(1);
	for(int j=1;(1<<j)<=n;j++)for(int i=1;i<=n;i++){
		if(f[i][j-1])f[i][j]=f[f[i][j-1]][j-1];
	}
	int m;scanf("%d",&m);
	for(int i=1;i<=m;i++){
		int u,v;
		scanf("%d%d",&u,&v);
		int LCA=lca(u,v);
		if(L[u]>L[v])swap(u,v);
		if(LCA==u)qu[i]=node(L[u],L[v],0,i);
		else  qu[i]=node(R[u],L[v],LCA,i);
	}
	work(m);
	for(int i=1;i<=m;i++)printf("%lld\n",ans[i]);
	return 0;
}


#include<vector>
#include<math.h>
#include<stdio.h>
#include<string.h>
#include<iostream>
#include<algorithm>
using namespace std;
typedef long long ll;
const int MAXN=(int)1e5+10;
struct edge{
	int to,nxt;
}ed[MAXN<<1];
int head[MAXN],cnt;
int f[MAXN][20],dep[MAXN];
void addedge(int u,int v){
	ed[cnt].to=v;
	ed[cnt].nxt=head[u];
	head[u]=cnt++;
}
vector<int>ve;
int a[MAXN],vl[MAXN];
int L[MAXN],R[MAXN],p[MAXN<<1],pos;
void dfs(int u){
	p[++pos]=u;
	L[u]=pos;
	for(int i=head[u];i!=-1;i=ed[i].nxt){
		int v=ed[i].to;
		if(!dep[v]){
			f[v][0]=u;
			dep[v]=dep[u]+1;
			dfs(v);
		}
	}
	p[++pos]=u;
	R[u]=pos;
}
int lca(int u,int v){
	if(dep[u]<dep[v])swap(u,v);
	for(int i=16;i>=0;i--){
		if(dep[f[u][i]]>=dep[v])u=f[u][i];
	}
	if(u==v)return u;
	for(int i=16;i>=0;i--){
		if(f[u][i]!=f[v][i])u=f[u][i],v=f[v][i];
	}
	return f[u][0];
}
struct node{
	int l,r,fa,idx;
	node(){}node(int _l,int _r,int _fa,int _idx){
		l=_l;r=_r;fa=_fa;idx=_idx;
	}
}qu[MAXN];
int len;
bool cmp(const node &a,const node &b){
	if(a.l/len==b.l/len)return a.r<b.r;
	else return a.l<b.l;
}
ll ans[MAXN];int vis[MAXN],mark[MAXN][2];
void ban(int x,ll &y){
	x=p[x];
	vis[x]^=1;
	if(vis[x]){
		mark[vl[x]][a[x]]++;
		y+=mark[vl[x]][a[x]^1];
	}
	else {
		mark[vl[x]][a[x]]--;
		y-=mark[vl[x]][a[x]^1];
	}
}int n;
void work(int m){
	int l,r;ll step=0;
	sort(qu+1,qu+1+m,cmp);
	l=qu[1].l,r=qu[1].l-1;
	for(int i=1;i<=m;i++){
		int ml,mr,idx,fa;
		ml=qu[i].l,mr=qu[i].r,idx=qu[i].idx,fa=qu[i].fa;
		while(l>ml)ban(--l,step);
		while(r<mr)ban(++r,step);
		while(l<ml)ban(l++,step);
		while(r>mr)ban(r--,step);
		ans[idx]=step;
		if(fa)ans[idx]+=mark[vl[fa]][a[fa]];
	}
}
int main()
{
	memset(head,-1,sizeof(head));
	scanf("%d",&n);
	len=(int)sqrt(n+n);
	for(int i=1;i<=n;i++)scanf("%d",&a[i]);
	for(int i=1;i<=n;i++)scanf("%d",&vl[i]),ve.push_back(vl[i]);
	sort(ve.begin(),ve.end());ve.erase(unique(ve.begin(),ve.end()),ve.end());
	for(int i=1;i<=n;i++)vl[i]=lower_bound(ve.begin(),ve.end(),vl[i])-ve.begin()+1;
	for(int i=1;i<n;i++){
		int u,v;
		scanf("%d%d",&u,&v);
		addedge(u,v);
		addedge(v,u);
	}
	dep[1]=1;
	dfs(1);
	for(int j=1;(1<<j)<=n;j++)for(int i=1;i<=n;i++){
		if(f[i][j-1])f[i][j]=f[f[i][j-1]][j-1];
	}
	int m;scanf("%d",&m);
	for(int i=1;i<=m;i++){
		int u,v;
		scanf("%d%d",&u,&v);
		int LCA=lca(u,v);
		if(L[u]>L[v])swap(u,v);
		if(LCA==u)qu[i]=node(L[u],L[v],0,i);
		else  qu[i]=node(R[u],L[v],LCA,i);
	}
	work(m);
	for(int i=1;i<=m;i++)printf("%lld\n",ans[i]);
	return 0;
}


#include<vector>
#include<math.h>
#include<stdio.h>
#include<string.h>
#include<iostream>
#include<algorithm>
using namespace std;
typedef long long ll;
const int MAXN=(int)1e5+10;
struct edge{
	int to,nxt;
}ed[MAXN<<1];
int head[MAXN],cnt;
int f[MAXN][20],dep[MAXN];
void addedge(int u,int v){
	ed[cnt].to=v;
	ed[cnt].nxt=head[u];
	head[u]=cnt++;
}
vector<int>ve;
int a[MAXN],vl[MAXN];
int L[MAXN],R[MAXN],p[MAXN<<1],pos;
void dfs(int u){
	p[++pos]=u;
	L[u]=pos;
	for(int i=head[u];i!=-1;i=ed[i].nxt){
		int v=ed[i].to;
		if(!dep[v]){
			f[v][0]=u;
			dep[v]=dep[u]+1;
			dfs(v);
		}
	}
	p[++pos]=u;
	R[u]=pos;
}
int lca(int u,int v){
	if(dep[u]<dep[v])swap(u,v);
	for(int i=16;i>=0;i--){
		if(dep[f[u][i]]>=dep[v])u=f[u][i];
	}
	if(u==v)return u;
	for(int i=16;i>=0;i--){
		if(f[u][i]!=f[v][i])u=f[u][i],v=f[v][i];
	}
	return f[u][0];
}
struct node{
	int l,r,fa,idx;
	node(){}node(int _l,int _r,int _fa,int _idx){
		l=_l;r=_r;fa=_fa;idx=_idx;
	}
}qu[MAXN];
int len;
bool cmp(const node &a,const node &b){
	if(a.l/len==b.l/len)return a.r<b.r;
	else return a.l<b.l;
}
ll ans[MAXN];int vis[MAXN],mark[MAXN][2];
void ban(int x,ll &y){
	x=p[x];
	vis[x]^=1;
	if(vis[x]){
		mark[vl[x]][a[x]]++;
		y+=mark[vl[x]][a[x]^1];
	}
	else {
		mark[vl[x]][a[x]]--;
		y-=mark[vl[x]][a[x]^1];
	}
}int n;
void work(int m){
	int l,r;ll step=0;
	sort(qu+1,qu+1+m,cmp);
	l=qu[1].l,r=qu[1].l-1;
	for(int i=1;i<=m;i++){
		int ml,mr,idx,fa;
		ml=qu[i].l,mr=qu[i].r,idx=qu[i].idx,fa=qu[i].fa;
		while(l>ml)ban(--l,step);
		while(r<mr)ban(++r,step);
		while(l<ml)ban(l++,step);
		while(r>mr)ban(r--,step);
		ans[idx]=step;
		if(fa)ans[idx]+=mark[vl[fa]][a[fa]^1];
	}
}
int main()
{
	memset(head,-1,sizeof(head));

	scanf("%d",&n);
	len=(int)sqrt(n+n);
	for(int i=1;i<=n;i++)scanf("%d",&a[i]);
	for(int i=1;i<=n;i++)scanf("%d",&vl[i]),ve.push_back(vl[i]);
	sort(ve.begin(),ve.end());ve.erase(unique(ve.begin(),ve.end()),ve.end());
	for(int i=1;i<=n;i++)vl[i]=lower_bound(ve.begin(),ve.end(),vl[i])-ve.begin()+1;
	for(int i=1;i<n;i++){
		int u,v;
		scanf("%d%d",&u,&v);
		addedge(u,v);
		addedge(v,u);
	}
	dep[1]=1;
	dfs(1);
	for(int i=1;i<=2*n;i++)printf("%d ",p[i]);
	printf("\n");
	for(int j=1;(1<<j)<=n;j++)for(int i=1;i<=n;i++){
		if(f[i][j-1])f[i][j]=f[f[i][j-1]][j-1];
	}
	int m;scanf("%d",&m);
	for(int i=1;i<=m;i++){
		int u,v;
		scanf("%d%d",&u,&v);
		int LCA=lca(u,v);
		if(L[u]>L[v])swap(u,v);
		if(LCA==u)qu[i]=node(L[u],L[v],0,i);
		else  qu[i]=node(R[u],L[v],LCA,i);
	}
	work(m);
	for(int i=1;i<=m;i++)printf("%lld\n",ans[i]);
	return 0;
}


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

int n,q,sex[xxx],num[xxx],tmp[xxx];
struct R{ int to,nex; }r[xxx];
int hea[xxx]={0},cnt=1;

int d[xxx],bsz,bel[xxx],used[23333],tim[xxx];
ll tot[2][xxx],ans,an[xxx];
int fa[xxx][20]={0},dft=0,df1[xxx],df2[xxx],dep[xxx]={0};
void dfs(int x,int fff){
	d[df1[x]=++dft]=x;
	fa[x][0]=fff;dep[x]=dep[fff]+1;
	for (int i=1;i<20;i++){
		if (dep[x]>(1<<i)){
			fa[x][i]=fa[fa[x][i-1]][i-1];
		}else{
			break;
		}
	}
	for (int i=hea[x],y;i>0;i=r[i].nex){
		y=r[i].to; if (y==fff) continue;
		dfs(y,x);
	}
	d[df2[x]=++dft]=x;
}
int lca(int x,int y){
	if (dep[x]<dep[y]) swap(x,y);
	for (int i=19;i>=0;i--){
		x= dep[fa[x][i]]>=dep[y] ? fa[x][i]:x;
	}
	if (x==y) return x;
	for (int i=19;i>=0;i--){
		if (fa[x][i]!=fa[y][i]){
			x=fa[x][i];y=fa[y][i];
		}
	}
	return fa[x][0];
}

struct Que{
	int st,en,more,id;
}que[xxx];
bool cmp(Que q1,Que q2){
	return bel[q1.st]==bel[q2.st] ? q1.en<q2.en : q1.st<q2.st;
}
void add(int w){
	ll fh=tim[w]?-1:1;
	ans+=fh*tot[sex[w]^1][num[w]];
	tot[sex[w]][num[w]]+=fh;
	tim[w]^=1;
}
void del(int w){
	ll fh=tim[w]?-1:1;
	ans-=fh*tot[sex[w]^1][num[w]];
	tot[sex[w]][num[w]]-=fh;
	tim[w]^=1;
}

int main(){
	scanf("%d",&n);
	for (int i=1;i<=n;scanf("%d",&sex[i++]));
	for (int i=1;i<=n;scanf("%d",&num[i++]));
	memcpy(tmp,num,sizeof tmp);
	sort(tmp+1,tmp+n+1);
	for (int i=1;i<=n;i++) num[i]=lower_bound(tmp+1,tmp+n+1,num[i])-tmp;
	for (int i=1,x,y;i<n;i++){
		scanf("%d%d",&x,&y);
		r[++cnt]=(R){y,hea[x]};hea[x]=cnt;
		r[++cnt]=(R){x,hea[y]};hea[y]=cnt;
	}
	dfs(1,0);
	bsz=sqrt(dft+0.1);
	for (int i=1;i<=dft;i++){
		bel[i]=(i-1)/bsz+1;
	}
	scanf("%d",&q);
	for (int i=1,x,y;i<=q;i++){
		scanf("%d%d",&x,&y);
		if (df1[x]>df1[y]) swap(x,y);
		if (df2[x]<=df1[y]) {
			que[i]=(Que){df2[x],df1[y],lca(x,y),i};
		}else{
			que[i]=(Que){df1[x],df1[y],0,i};
		}
	}
	sort(que+1,que+q+1,cmp);

	memset(used,0,sizeof used);
	for (int i=1,l,r;i<=q;i++){
		if (!used[bel[que[i].st]]){
			used[bel[que[i].st]]=1;
			memset(tot,0,sizeof tot);
			memset(tim,0,sizeof tim);
			ans=0;
			l=que[i].st;r=l-1;
		}
		while (r<que[i].en) add(d[++r]);
		while (l>que[i].st) add(d[--l]);
		while (l<que[i].st) del(d[l++]);
		if (que[i].more) add(que[i].more);
		an[que[i].id]=ans;
		if (que[i].more) del(que[i].more);
	}
	for (int i=1;i<=q;printf("%I64d\n",an[i++]));
}


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

int n,q,sex[xxx],num[xxx],tmp[xxx];
struct R{ int to,nex; }r[xxx];
int hea[xxx]={0},cnt=1;

int d[xxx],bsz,bel[xxx],used[23333],tim[xxx];
ll tot[2][xxx],ans,an[xxx];
int fa[xxx][20]={0},dft=0,df1[xxx],df2[xxx],dep[xxx]={0};
void dfs(int x,int fff){
	d[df1[x]=++dft]=x;
	fa[x][0]=fff;dep[x]=dep[fff]+1;
	for (int i=1;i<20;i++){
		if (dep[x]>(1<<i)){
			fa[x][i]=fa[fa[x][i-1]][i-1];
		}else{
			break;
		}
	}
	for (int i=hea[x],y;i>0;i=r[i].nex){
		y=r[i].to; if (y==fff) continue;
		dfs(y,x);
	}
	d[df2[x]=++dft]=x;
}
int lca(int x,int y){
	if (dep[x]<dep[y]) swap(x,y);
	for (int i=19;i>=0;i--){
		x= dep[fa[x][i]]>=dep[y] ? fa[x][i]:x;
	}
	if (x==y) return x;
	for (int i=19;i>=0;i--){
		if (fa[x][i]!=fa[y][i]){
			x=fa[x][i];y=fa[y][i];
		}
	}
	return fa[x][0];
}

struct Que{
	int st,en,more,id;
}que[xxx];
bool cmp(Que q1,Que q2){
	return bel[q1.st]==bel[q2.st] ? q1.en<q2.en : q1.st<q2.st;
}
void add(int w){
	ll fh=tim[w]?-1:1;
	ans+=fh*tot[sex[w]^1][num[w]];
	tot[sex[w]][num[w]]+=fh;
	tim[w]^=1;
}
void del(int w){
	ll fh=tim[w]?1:-1;
	ans-=fh*tot[sex[w]^1][num[w]];
	tot[sex[w]][num[w]]-=fh;
	tim[w]^=1;
}

int main(){
	scanf("%d",&n);
	for (int i=1;i<=n;scanf("%d",&sex[i++]));
	for (int i=1;i<=n;scanf("%d",&num[i++]));
	memcpy(tmp,num,sizeof tmp);
	sort(tmp+1,tmp+n+1);
	for (int i=1;i<=n;i++) num[i]=lower_bound(tmp+1,tmp+n+1,num[i])-tmp;
	for (int i=1,x,y;i<n;i++){
		scanf("%d%d",&x,&y);
		r[++cnt]=(R){y,hea[x]};hea[x]=cnt;
		r[++cnt]=(R){x,hea[y]};hea[y]=cnt;
	}
	dfs(1,0);
	bsz=sqrt(dft+0.1);
	for (int i=1;i<=dft;i++){
		bel[i]=(i-1)/bsz+1;
	}
	scanf("%d",&q);
	for (int i=1,x,y;i<=q;i++){
		scanf("%d%d",&x,&y);
		if (df1[x]>df1[y]) swap(x,y);
		if (df2[x]<=df1[y]) {
			que[i]=(Que){df2[x],df1[y],lca(x,y),i};
		}else{
			que[i]=(Que){df1[x],df1[y],0,i};
		}
	}
	sort(que+1,que+q+1,cmp);

	memset(used,0,sizeof used);
	for (int i=1,l,r;i<=q;i++){
		//printf(" %d %d %d %d\n",que[i].id,que[i].st,que[i].en,que[i].more);
		if (!used[bel[que[i].st]]){
			used[bel[que[i].st]]=1;
			memset(tot,0,sizeof tot);
			memset(tim,0,sizeof tim);
			ans=0;
			l=que[i].st;r=l-1;
		}
		while (r<que[i].en) add(d[++r]);
		while (l>que[i].st) add(d[--l]);
		while (l<que[i].st) del(d[l++]);
		if (que[i].more) add(que[i].more);
		an[que[i].id]=ans;
		if (que[i].more) del(que[i].more);
	}
	for (int i=1;i<=q;printf("%I64d\n",an[i++]));
}


    #include<bits/stdc++.h>

    using namespace std;

    typedef long long ll;
    typedef long double ld;
    typedef pair<int, int> pi;
    typedef vector<int> vi;
    typedef vector<ll> vll;
    typedef vector<vll> vvll;
    typedef vector<vi> vvi;
    typedef vector<pi> vpi;
    typedef vector<vpi> vvpi;

    vvi G;
    const int L = 20;
    vvi D;
    vi P;
    vpi A;
    vi C;
    int cont;

    void dfs(int x, int d = 0, int p = -1) {
      C[cont] = x;
      A[x].first = cont++;
      P[x] = d;
      D[x][0] = p;
      int l = 0;
      while (D[x][l] != -1) {
        D[x][l+1] = D[D[x][l]][l];
        l++;
      }
      for (auto y : G[x]) {
        if (y == p) continue;
        dfs(y, d+1, x);
      }
      C[cont] = x;
      A[x].second = cont++;
    }

    int lca(int x, int y) {
      if (P[x] < P[y]) swap(x, y);
      int l = L;
      while (l--) {
        int x0 = D[x][l];
        if (x0 != -1 and P[x0] >= P[y]) x = x0;
      }
      if (x == y) return x;
      l = L;
      while (l--) {
        int x0 = D[x][l];
        int y0 = D[y][l];
        if (x0 != y0) {
          x = x0;
          y = y0;
        }
      }
      return D[x][0];
    }

    struct que {
      int a, b, lc;
      int ind;
    };

    const int S = 320;

    bool comp(que a, que b) {
      int x = a.a/S;
      int y = b.a/S;
      if (x != y) return x < y;
      return (x&1 ? a.b > b.b : a.b < b.b);
    }

    inline void fes(int x, vvll& tt, vpi& V, vi& vist, ll& res) {
        vist[x] ^= 1;
        if (vist[x]) {
          res += tt[V[x].first^1][V[x].second];
          ++tt[V[x].first][V[x].second];
        }
        else {
          res -= tt[V[x].first^1][V[x].second];
          --tt[V[x].first][V[x].second];
        }
    }

    int main() {
      ios_base::sync_with_stdio(false);
      cin.tie(0);
      int n;
      cin >> n;
      G = vvi(n);
      D =vvi(n, vi(L, -1));
      P = vi(n);
      vpi V(n);
      cont = 0;
      C = vi(2*n);
      A = vpi(n);
      for (int i = 0; i < n; ++i) cin >> V[i].first;
      vi cc(n);
      for (int i = 0; i < n; ++i) {
        cin >> V[i].second;
        cc[i] = V[i].second;
      }
      sort(cc.begin(), cc.end());
      int sz = unique(cc.begin(), cc.end()) - cc.begin();
      map<int, int> M;
      for (int i = 0; i < sz; ++i) M[cc[i]] = i;
      for (int i = 0; i < n; ++i) V[i].second = M[V[i].second];
      for (int i = 1; i < n; ++i) {
        int a, b;
        cin >> a >> b;
        --a; --b;
        G[a].push_back(b);
        G[b].push_back(a);
      }
      dfs(0);
      int m;
      cin >> m;
      vector<que> Q(m);
      for (int i = 0; i < m; ++i) {
        int a, b;
        cin >> a >> b;
        --a; --b;
        Q[i].ind = i;
        if (A[b].first < A[a].first) swap(a, b);
        if (A[a].second >= A[b].second) {
          Q[i].a = A[a].first;
          Q[i].b = A[b].first;
          Q[i].lc = -1;
        }
        else {
          Q[i].a = A[a].second;
          Q[i].b = A[b].first;
          Q[i].lc = lca(a, b);
        }
      }
      sort(Q.begin(), Q.end(), comp);
      vll R(m);
      vvll tt(2, vll(sz, 0));
      vi vist(n, 0);
      ll res = 0;
      int b = -1;
      int a = 0;
      for (auto q : Q) {
        while (b < q.b) {
          ++b;
          int x = C[b];
          fes(x, tt, V, vist, res);
        }
        while (a > q.a) {
          --a;
          int x = C[a];
          fes(x, tt, V, vist, res);
        }
        while (b > q.b) {
          int x = C[b];
          fes(x, tt, V, vist, res);
          --b;
        }
        while (a < q.a) {
          int x = C[a];
          fes(x, tt, V, vist, res);
          ++a;
        }

        if (q.lc != -1) {
          fes(q.lc, tt, V, vist, res);
        }
        R[q.ind] = res;
        if (q.lc != -1) {
          fes(q.lc, tt, V, vist, res);
        }
      }
      for (auto r : R) cout << r << '\n';
    }


/*input
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
1 3
7 5

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

using namespace std;

struct uzklausa {
	int l, r, i, p;
};

int depth[100000] = {}, parent[17][100000];
int start[100000], endd[100000];

void dfs(int i, vector<int> gra[], vector<int> &tvark, vector<bool> &apl) {
	start[i] = tvark.size();
	tvark.push_back(i);
	apl[i] = true;

	for (auto && x : gra[i]) {
		if (!apl[x]) {
			depth[x] = depth[i] + 1;
			parent[0][x] = i;
			dfs(x, gra, tvark, apl);
		}
	}

	endd[i] = tvark.size();
	tvark.push_back(i);
}

int lca(int u, int v) {
	if (depth[u] < depth[v]) swap(u, v);

	int diff = depth[u] - depth[v];

	for (int i = 0; i < 17; i++) {
		if ((diff >> i) & 1)
			u = parent[i][u];
	}

	if (u == v) return u;

	for (int i = 17 - 1; i >= 0; i--) {
		if (parent[i][u] != parent[i][v]) {
			u = parent[i][u];
			v = parent[i][v];
		}
	}

	return parent[0][u];
}

int main () {
	int n;
	cin >> n;
	bool lyt[n];

	for (int i = 0; i < n; i++)
		cin >> lyt[i];

	map<int, int> numer;
	int myl[n];

	for (int i = 0; i < n; i++) {
		cin >> myl[i];

		if (numer.find(myl[i]) == numer.end())
			numer[myl[i]] = numer.size() - 1;

		myl[i] = numer[myl[i]];
	}

	vector<int> gra[n];

	for (int i = 1; i < n; i++) {
		int a, b;
		cin >> a >> b;
		a--, b--;
		gra[a].push_back(b);
		gra[b].push_back(a);
	}

	vector<int> tvark;
	{
		vector<bool> apl(n, false);
		dfs(0, gra, tvark, apl);
	}

	int q;
	cin >> q;

	uzklausa uzk[q];

	for (int i = 0; i < q; i++) {
		cin >> uzk[i].l >> uzk[i].r;
		uzk[i].l--, uzk[i].r--;
		uzk[i].i = i;

		if (start[uzk[i].l] > start[uzk[i].r]) swap(uzk[i].l, uzk[i].r);

		uzk[i].p = lca(uzk[i].l, uzk[i].r);

		if (uzk[i].p == uzk[i].l) {
			uzk[i].p = -1;
			uzk[i].l = start[uzk[i].l];
			uzk[i].r = start[uzk[i].r];
		}
		else {
			uzk[i].l = endd[uzk[i].l];
			uzk[i].r = start[uzk[i].r];
		}
	}

	long long k = sqrt(n);

	sort(uzk, uzk + q, [&](const auto & i, const auto & j) -> bool {
		return make_pair(i.l / k, i.r) < make_pair(j.l / k, j.r);
	});

	long long ats[q];

	bool prid[n] = {};
	long long kiek[n][2] = {};
	int pl = 0, pr = 0;
	long long atst = 0;

	auto toggle = [&](int u) {
		atst -= kiek[myl[u]][0] * kiek[myl[u]][1];

		if (prid[u])
			kiek[myl[u]][lyt[u]]--;
		else
			kiek[myl[u]][lyt[u]]++;

		/*cout << endl;
		cout << u << " " << myl[u] << " " << lyt[u] << endl;
		cout << kiek[0][0] << " " << kiek[0][1] << endl;
		cout << kiek[1][0] << " " << kiek[1][1] << endl;
		cout << endl;*/

		prid[u] ^= 1;

		atst += kiek[myl[u]][0] * kiek[myl[u]][1];
	};

	toggle(0);

	for (int i = 0; i < q; i++) {
		cout << uzk[i].l << " " << uzk[i].r << endl;

		while (pl > uzk[i].l)
			toggle(tvark[--pl]);

		while (pr < uzk[i].r)
			toggle(tvark[++pr]);

		while (pl < uzk[i].l)
			toggle(tvark[pl++]);

		while (pr > uzk[i].r)
			toggle(tvark[pr--]);

		if (uzk[i].p != -1) toggle(uzk[i].p);

		/*cout << endl;
		cout << kiek[0][0] << " " << kiek[0][1] << endl;
		cout << kiek[1][0] << " " << kiek[1][1] << endl;
		cout << endl;*/

		ats[uzk[i].i] = atst;

		if (uzk[i].p != -1) toggle(uzk[i].p);
	}

	for (int i = 0; i < q; i++)
		cout << ats[i] << "\n";

	return 0;
}


/*input
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
1 3
7 5

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

using namespace std;

struct uzklausa {
	int l, r, i, p;
};

int depth[100000] = {}, parent[17][100000];
int start[100000], endd[100000];

void dfs(int i, vector<int> gra[], vector<int> &tvark, vector<bool> &apl) {
	start[i] = tvark.size();
	tvark.push_back(i);
	apl[i] = true;

	for (auto && x : gra[i]) {
		if (!apl[x]) {
			depth[x] = depth[i] + 1;
			parent[0][x] = i;
			dfs(x, gra, tvark, apl);
		}
	}

	endd[i] = tvark.size();
	tvark.push_back(i);
}

int lca(int u, int v) {
	if (depth[u] < depth[v]) swap(u, v);

	int diff = depth[u] - depth[v];

	for (int i = 0; i < 17; i++) {
		if ((diff >> i) & 1)
			u = parent[i][u];
	}

	if (u == v) return u;

	for (int i = 17 - 1; i >= 0; i--) {
		if (parent[i][u] != parent[i][v]) {
			u = parent[i][u];
			v = parent[i][v];
		}
	}

	return parent[0][u];
}

int main () {
	int n;
	cin >> n;
	bool lyt[n];

	for (int i = 0; i < n; i++)
		cin >> lyt[i];

	map<int, int> numer;
	int myl[n];

	for (int i = 0; i < n; i++) {
		cin >> myl[i];

		if (numer.find(myl[i]) == numer.end())
			numer[myl[i]] = numer.size() - 1;

		myl[i] = numer[myl[i]];
	}

	vector<int> gra[n];

	for (int i = 1; i < n; i++) {
		int a, b;
		cin >> a >> b;
		a--, b--;
		gra[a].push_back(b);
		gra[b].push_back(a);
	}

	vector<int> tvark;
	{
		vector<bool> apl(n, false);
		dfs(0, gra, tvark, apl);
	}

	int q;
	cin >> q;

	uzklausa uzk[q];

	for (int i = 0; i < q; i++) {
		cin >> uzk[i].l >> uzk[i].r;
		uzk[i].l--, uzk[i].r--;
		uzk[i].i = i;

		if (start[uzk[i].l] > start[uzk[i].r]) swap(uzk[i].l, uzk[i].r);

		uzk[i].p = lca(uzk[i].l, uzk[i].r);

		if (uzk[i].p == uzk[i].l) {
			uzk[i].p = -1;
			uzk[i].l = start[uzk[i].l];
			uzk[i].r = start[uzk[i].r];
		}
		else {
			uzk[i].l = endd[uzk[i].l];
			uzk[i].r = start[uzk[i].r];
		}
	}

	long long k = sqrt(n);

	sort(uzk, uzk + q, [&](const auto & i, const auto & j) -> bool {
		return make_pair(i.l / k, i.r) < make_pair(j.l / k, j.r);
	});

	long long ats[q];

	bool prid[n] = {};
	long long kiek[n][2] = {};
	int pl = 0, pr = 0;
	long long atst = 0;

	auto toggle = [&](int u) {
		atst -= kiek[myl[u]][0] * kiek[myl[u]][1];

		if (prid[u])
			kiek[myl[u]][lyt[u]]--;
		else
			kiek[myl[u]][lyt[u]]++;

		/*cout << endl;
		cout << u << " " << myl[u] << " " << lyt[u] << endl;
		cout << kiek[0][0] << " " << kiek[0][1] << endl;
		cout << kiek[1][0] << " " << kiek[1][1] << endl;
		cout << endl;*/

		prid[u] ^= 1;

		atst += kiek[myl[u]][0] * kiek[myl[u]][1];
	};

	toggle(0);

	for (int i = 0; i < q; i++) {
		//cout << uzk[i].l << " " << uzk[i].r << endl;

		while (pl > uzk[i].l)
			toggle(tvark[--pl]);

		while (pr < uzk[i].r)
			toggle(tvark[++pr]);

		while (pl < uzk[i].l)
			toggle(tvark[pl++]);

		while (pr > uzk[i].r)
			toggle(tvark[pr--]);

		if (uzk[i].p != -1) toggle(uzk[i].p);

		/*cout << endl;
		cout << kiek[0][0] << " " << kiek[0][1] << endl;
		cout << kiek[1][0] << " " << kiek[1][1] << endl;
		cout << endl;*/

		ats[uzk[i].i] = atst;

		if (uzk[i].p != -1) toggle(uzk[i].p);
	}

	for (int i = 0; i < q; i++)
		cout << ats[i] << "\n";

	return 0;
}


/*input
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
1 3
7 5
*/
#include <bits/stdc++.h>

using namespace std;

struct uzklausa {
	int l, r, i, p;
};

int depth[100000] = {}, parent[17][100000];
int start[100000], endd[100000];

void dfs(int i, vector<int> gra[], vector<int> &tvark, vector<bool> &apl) {
	start[i] = tvark.size();
	tvark.push_back(i);
	apl[i] = true;

	for (auto && x : gra[i]) {
		if (!apl[x]) {
			depth[x] = depth[i] + 1;
			parent[0][x] = i;
			dfs(x, gra, tvark, apl);
		}
	}

	endd[i] = tvark.size();
	tvark.push_back(i);
}

int lca(int u, int v) {
	if (depth[u] < depth[v]) swap(u, v);

	int diff = depth[u] - depth[v];

	for (int i = 0; i < 17; i++) {
		if ((diff >> i) & 1)
			u = parent[i][u];
	}

	if (u == v) return u;

	for (int i = 17 - 1; i >= 0; i--) {
		if (parent[i][u] != parent[i][v]) {
			u = parent[i][u];
			v = parent[i][v];
		}
	}

	return parent[0][u];
}

int main () {
	int n;
	cin >> n;
	bool lyt[n];

	for (int i = 0; i < n; i++)
		cin >> lyt[i];

	map<int, int> numer;
	int myl[n];

	for (int i = 0; i < n; i++) {
		cin >> myl[i];

		if (numer.find(myl[i]) == numer.end())
			numer[myl[i]] = numer.size() - 1;

		myl[i] = numer[myl[i]];
	}

	vector<int> gra[n];

	for (int i = 1; i < n; i++) {
		int a, b;
		cin >> a >> b;
		a--, b--;
		gra[a].push_back(b);
		gra[b].push_back(a);
	}

	vector<int> tvark;
	{
		vector<bool> apl(n, false);
		dfs(0, gra, tvark, apl);

		for (int i = 1; i < 17; i++) {
			for (int j = 0; j < n; j++) {
				if (parent[i - 1][j] != -1)
					parent[i][j] = parent[i - 1][parent[i - 1][j]];
			}
		}
	}

	int q;
	cin >> q;

	uzklausa uzk[q];

	for (int i = 0; i < q; i++) {
		cin >> uzk[i].l >> uzk[i].r;
		uzk[i].l--, uzk[i].r--;
		uzk[i].i = i;

		if (start[uzk[i].l] > start[uzk[i].r]) swap(uzk[i].l, uzk[i].r);

		uzk[i].p = lca(uzk[i].l, uzk[i].r);

		if (uzk[i].p == uzk[i].l) {
			uzk[i].p = -1;
			uzk[i].l = start[uzk[i].l];
			uzk[i].r = start[uzk[i].r];
		}
		else {
			uzk[i].l = endd[uzk[i].l];
			uzk[i].r = start[uzk[i].r];
		}
	}

	long long k = sqrt(2 * n);

	sort(uzk, uzk + q, [&](const auto & i, const auto & j) -> bool {
		return make_pair(i.l / k, i.r) < make_pair(j.l / k, j.r);
	});

	long long ats[q];

	bool prid[n] = {};
	long long kiek[n][2] = {};
	int pl = 0, pr = 0;
	long long atst = 0;

	auto toggle = [&](int u) {
		atst -= kiek[myl[u]][0] * kiek[myl[u]][1];

		if (prid[u])
			kiek[myl[u]][lyt[u]]--;
		else
			kiek[myl[u]][lyt[u]]++;

		/*cout << endl;
		cout << u << " " << myl[u] << " " << lyt[u] << endl;
		cout << kiek[0][0] << " " << kiek[0][1] << endl;
		cout << kiek[1][0] << " " << kiek[1][1] << endl;
		cout << endl;*/

		prid[u] ^= 1;

		atst += kiek[myl[u]][0] * kiek[myl[u]][1];
	};

	toggle(0);

	for (int i = 0; i < q; i++) {
		//cout << uzk[i].l << " " << uzk[i].r << endl;

		while (pl > uzk[i].l)
			toggle(tvark[--pl]);

		while (pr < uzk[i].r)
			toggle(tvark[++pr]);

		while (pl < uzk[i].l)
			toggle(tvark[pl++]);

		while (pr > uzk[i].r)
			toggle(tvark[pr--]);

		if (uzk[i].p != -1) toggle(uzk[i].p);

		/*cout << endl;
		cout << kiek[0][0] << " " << kiek[0][1] << endl;
		cout << kiek[1][0] << " " << kiek[1][1] << endl;
		cout << endl;*/

		/*for (int i = 0; i < n; i++)
			cout << prid[i] << " ";

		cout << endl;*/

		ats[uzk[i].i] = atst;

		if (uzk[i].p != -1) toggle(uzk[i].p);
	}

	for (int i = 0; i < q; i++)
		cout << ats[i] << "\n";

	return 0;
}


/*input
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
1 3
7 5
*/
#include <bits/stdc++.h>

using namespace std;

struct uzklausa {
	int l, r, i, p;
};

int depth[100000] = {}, parent[17][100000];
int start[100000], endd[100000];

void dfs(int i, vector<int> gra[], vector<int> &tvark, vector<bool> &apl) {
	start[i] = tvark.size();
	tvark.push_back(i);
	apl[i] = true;

	for (auto && x : gra[i]) {
		if (!apl[x]) {
			depth[x] = depth[i] + 1;
			parent[0][x] = i;
			dfs(x, gra, tvark, apl);
		}
	}

	endd[i] = tvark.size();
	tvark.push_back(i);
}

int lca(int u, int v) {
	if (depth[u] < depth[v]) swap(u, v);

	int diff = depth[u] - depth[v];

	for (int i = 0; i < 17; i++) {
		if ((diff >> i) & 1)
			u = parent[i][u];
	}

	if (u == v) return u;

	for (int i = 17 - 1; i >= 0; i--) {
		if (parent[i][u] != parent[i][v]) {
			u = parent[i][u];
			v = parent[i][v];
		}
	}

	return parent[0][u];
}

int main () {
	ios_base::sync_with_stdio(false), cin.tie(0), cout.tie(0);
	int n;
	cin >> n;
	bool lyt[n];

	for (int i = 0; i < n; i++)
		cin >> lyt[i];

	map<int, int> numer;
	int myl[n];

	for (int i = 0; i < n; i++) {
		cin >> myl[i];

		if (numer.find(myl[i]) == numer.end())
			numer[myl[i]] = numer.size() - 1;

		myl[i] = numer[myl[i]];
	}

	vector<int> gra[n];

	for (int i = 1; i < n; i++) {
		int a, b;
		cin >> a >> b;
		a--, b--;
		gra[a].push_back(b);
		gra[b].push_back(a);
	}

	vector<int> tvark;
	{
		vector<bool> apl(n, false);
		dfs(0, gra, tvark, apl);

		for (int i = 1; i < 17; i++) {
			for (int j = 0; j < n; j++) {
				if (parent[i - 1][j] != -1)
					parent[i][j] = parent[i - 1][parent[i - 1][j]];
			}
		}
	}

	int q;
	cin >> q;

	uzklausa uzk[q];

	for (int i = 0; i < q; i++) {
		cin >> uzk[i].l >> uzk[i].r;
		uzk[i].l--, uzk[i].r--;
		uzk[i].i = i;

		if (start[uzk[i].l] > start[uzk[i].r]) swap(uzk[i].l, uzk[i].r);

		uzk[i].p = lca(uzk[i].l, uzk[i].r);

		if (uzk[i].p == uzk[i].l) {
			uzk[i].p = -1;
			uzk[i].l = start[uzk[i].l];
			uzk[i].r = start[uzk[i].r];
		}
		else {
			uzk[i].l = endd[uzk[i].l];
			uzk[i].r = start[uzk[i].r];
		}
	}

	long long k = sqrt(2 * n);

	sort(uzk, uzk + q, [&](const auto & i, const auto & j) -> bool {
		return make_pair(i.l / k, i.r) < make_pair(j.l / k, j.r);
	});

	long long ats[q];

	bool prid[n] = {};
	long long kiek[n][2] = {};
	int pl = 0, pr = 0;
	long long atst = 0;

	auto toggle = [&](int u) {
		atst -= kiek[myl[u]][0] * kiek[myl[u]][1];

		if (prid[u])
			kiek[myl[u]][lyt[u]]--;
		else
			kiek[myl[u]][lyt[u]]++;

		/*cout << endl;
		cout << u << " " << myl[u] << " " << lyt[u] << endl;
		cout << kiek[0][0] << " " << kiek[0][1] << endl;
		cout << kiek[1][0] << " " << kiek[1][1] << endl;
		cout << endl;*/

		prid[u] ^= 1;

		atst += kiek[myl[u]][0] * kiek[myl[u]][1];
	};

	toggle(0);

	for (int i = 0; i < q; i++) {
		//cout << uzk[i].l << " " << uzk[i].r << endl;

		while (pl > uzk[i].l)
			toggle(tvark[--pl]);

		while (pr < uzk[i].r)
			toggle(tvark[++pr]);

		while (pl < uzk[i].l)
			toggle(tvark[pl++]);

		while (pr > uzk[i].r)
			toggle(tvark[pr--]);

		if (uzk[i].p != -1) toggle(uzk[i].p);

		ats[uzk[i].i] = atst;

		if (uzk[i].p != -1) toggle(uzk[i].p);
	}

	for (int i = 0; i < q; i++)
		cout << ats[i] << "\n";

	return 0;
}


/*input
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
1 3
7 5

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

using namespace std;

struct uzklausa {
	int l, r, i, p;
};

int depth[100000] = {}, parent[17][100000];
int start[100000], endd[100000];

void dfs(int i, vector<int> gra[], vector<int> &tvark, vector<bool> &apl) {
	start[i] = tvark.size();
	tvark.push_back(i);
	apl[i] = true;

	for (auto && x : gra[i]) {
		if (!apl[x]) {
			depth[x] = depth[i] + 1;
			parent[0][x] = i;
			dfs(x, gra, tvark, apl);
		}
	}

	endd[i] = tvark.size();
	tvark.push_back(i);
}

int lca(int u, int v) {
	if (depth[u] < depth[v]) swap(u, v);

	int diff = depth[u] - depth[v];

	for (int i = 0; i < 17; i++) {
		if ((diff >> i) & 1)
			u = parent[i][u];
	}

	if (u == v) return u;

	for (int i = 17 - 1; i >= 0; i--) {
		if (parent[i][u] != parent[i][v]) {
			u = parent[i][u];
			v = parent[i][v];
		}
	}

	return parent[0][u];
}

int main () {
	ios_base::sync_with_stdio(false), cin.tie(0), cout.tie(0);
	int n;
	cin >> n;
	bool lyt[n];

	for (int i = 0; i < n; i++)
		cin >> lyt[i];

	map<int, int> numer;
	int myl[n];

	for (int i = 0; i < n; i++) {
		cin >> myl[i];

		if (numer.find(myl[i]) == numer.end())
			numer[myl[i]] = numer.size() - 1;

		myl[i] = numer[myl[i]];
	}

	vector<int> gra[n];

	for (int i = 1; i < n; i++) {
		int a, b;
		cin >> a >> b;
		a--, b--;
		gra[a].push_back(b);
		gra[b].push_back(a);
	}

	vector<int> tvark;
	{
		vector<bool> apl(n, false);
		dfs(0, gra, tvark, apl);
	}

	int q;
	cin >> q;

	uzklausa uzk[q];

	for (int i = 0; i < q; i++) {
		cin >> uzk[i].l >> uzk[i].r;
		uzk[i].l--, uzk[i].r--;
		uzk[i].i = i;

		if (start[uzk[i].l] > start[uzk[i].r]) swap(uzk[i].l, uzk[i].r);

		uzk[i].p = lca(uzk[i].l, uzk[i].r);

		if (uzk[i].p == uzk[i].l) {
			uzk[i].p = -1;
			uzk[i].l = start[uzk[i].l];
			uzk[i].r = start[uzk[i].r];
		}
		else {
			uzk[i].l = endd[uzk[i].l];
			uzk[i].r = start[uzk[i].r];
		}
	}

	long long k = sqrt(n);

	sort(uzk, uzk + q, [&](const auto & i, const auto & j) -> bool {
		return make_pair(i.l / k, i.r) < make_pair(j.l / k, j.r);
	});

	long long ats[q];

	bool prid[n] = {};
	int kiek[n][2] = {};
	int pl = 0, pr = 0;
	long long atst = 0;

	auto toggle = [&](int u) {
		atst -= kiek[myl[u]][0] * kiek[myl[u]][1];

		if (prid[u])
			kiek[myl[u]][lyt[u]]--;
		else
			kiek[myl[u]][lyt[u]]++;

		/*cout << endl;
		cout << u << " " << myl[u] << " " << lyt[u] << endl;
		cout << kiek[0][0] << " " << kiek[0][1] << endl;
		cout << kiek[1][0] << " " << kiek[1][1] << endl;
		cout << endl;*/

		prid[u] ^= 1;

		atst += kiek[myl[u]][0] * kiek[myl[u]][1];
	};
/*
	for (int i = 0; i < tvark.size(); i++)
		cout << tvark[i] << " ";

	cout << endl;

	for (int i = 0; i < n; i++)
		cout << myl[i] << " ";

	cout << endl;

	for (int i = 0; i < n; i++)
		cout << lyt[i] << " ";

	cout << endl;*/

	toggle(0);

	for (int i = 0; i < q; i++) {
		//cout << uzk[i].l << " " << uzk[i].r << endl;

		while (pl > uzk[i].l)
			toggle(tvark[--pl]);

		while (pr < uzk[i].r)
			toggle(tvark[++pr]);

		while (pl < uzk[i].l)
			toggle(tvark[pl++]);

		while (pr > uzk[i].r)
			toggle(tvark[pr--]);

		if (uzk[i].p != -1) toggle(uzk[i].p);

		/*cout << endl;
		cout << kiek[0][0] << " " << kiek[0][1] << endl;
		cout << kiek[1][0] << " " << kiek[1][1] << endl;
		cout << endl;*/

		ats[uzk[i].i] = atst;

		if (uzk[i].p != -1) toggle(uzk[i].p);
	}

	for (int i = 0; i < q; i++)
		cout << ats[i] << "\n";

	return 0;
}


#include <iostream>
#include <algorithm>
#include <cstdio>
#include <vector>
#include <cmath>
#include <complex>
#include <queue>
#include <map>
#include <set>
#include <bitset>
#include <iomanip>
#include <ctime>
//#include <unordered_map>
#define ll long long
#define MAXN 100005
#define INF 1000000000LL
//#define y second
//#define x first
#define int long long
#define fpos fuuuu
//#define double long double

using namespace std;

int T;
int n, q, i, b[MAXN], f[MAXN];
vector <int> g[MAXN];

struct query{
    int id, a, b, l, r;
} h[MAXN];

int p[20][MAXN], d[MAXN], a[MAXN];
int in[MAXN], out[MAXN], timer;

int dfs(int v){
    int to, i;

    a[timer] = v;
    in[v] = timer++;

    for(i = 1; i < 20; i++)
        p[i][v] = p[i - 1][p[i - 1][v]];

    for(i = 0; i < g[v].size(); i++){
        to = g[v][i];

        if(p[0][v] == to)
            continue;

        p[0][to] = v;
        d[to] = d[v] + 1;

        dfs(to);
    }

    a[timer] = v;
    out[v] = timer++;
}

int getLCA(int a, int b){
    int i;

    if(d[a] < d[b])
        swap(a, b);

    for(i = 19; i >= 0; i--){
        if(d[b] - d[a] >= (1 << i))
            a = p[i][a];
    }

    if(a == b)
        return a;

    for(i = 19; i >= 0; i--){
        if(p[i][a] != p[i][b]){
            a = p[i][a];
            b = p[i][b];
        }
    }

    return p[0][a];
}

bool cmp(query x, query y){
    if(x.l / T == y.l / T)
        return x.r < y.r;
    return x.l < y.l;
}

int cnt[MAXN], c[2][MAXN], ans[MAXN], ANS;

int add(int x){
    cnt[x]++;

    if(cnt[x] == 2){
        ANS -= c[b[x] ^ 1][f[x]];
        c[b[x]][f[x]]--;
    }
    else{
        ANS += c[b[x] ^ 1][f[x]];
        c[b[x]][f[x]]++;
    }
}

int del(int x){
    cnt[x]--;

    if(cnt[x] == 1){
        ANS += c[b[x] ^ 1][f[x]];
        c[b[x]][f[x]]++;
    }
    else{
        ANS -= c[b[x] ^ 1][f[x]];
        c[b[x]][f[x]]--;
    }
}

main(){
    //freopen("input.txt", "r", stdin);
    //freopen("output.txt", "w", stdout);

    ios_base::sync_with_stdio(0);
    cin.tie();

    cin >> n;

    for(i = 0; i < n; i++)
        cin >> b[i];

    map <int, int> mp;
    int sz = 0;

    for(i = 0; i < n; i++){
        cin >> f[i];
        if(!mp.count(f[i]))
            mp[f[i]] = sz++;
        f[i] = mp[f[i]];
    }

    for(i = 0; i < n - 1; i++){
        int a, b;
        cin >> a >> b;
        a--; b--;
        g[a].push_back(b);
        g[b].push_back(a);
    }

    dfs(0);

    cin >> q;

    T = sqrt(n);

    for(i = 0; i < q; i++){
        cin >> h[i].a >> h[i].b;
        h[i].a--; h[i].b--;
        h[i].id = i;

        if(in[h[i].a] > in[h[i].b])
            swap(h[i].a, h[i].b);

        h[i].l = in[h[i].a] + 1;
        h[i].r = out[h[i].b] - 1;
    }

    sort(h, h + q, cmp);

    int l = 0, r = -1;

    for(i = 0; i < q; i++){
        while(l < h[i].l){
            del(a[l]);
            l++;
        }

        while(l > h[i].l){
            add(a[l - 1]);
            l--;
        }

        while(r < h[i].r){
            add(a[r + 1]);
            r++;
        }

        while(r > h[i].r){
            del(a[r]);
            r--;
        }

        add(a[in[getLCA(h[i].a, h[i].b)]]);

        ans[h[i].id] = ANS;

        del(a[in[getLCA(h[i].a, h[i].b)]]);
    }

    for(i = 0; i < q; i++)
        cout << ans[i] << endl;
    return 0;
}


#include <iostream>
#include <algorithm>
#include <cstdio>
#include <vector>
#include <cmath>
#include <complex>
#include <queue>
#include <map>
#include <set>
#include <bitset>
#include <iomanip>
#include <ctime>
//#include <unordered_map>
#define ll long long
#define MAXN 100005
#define INF 1000000000LL
//#define y second
//#define x first
#define int long long
#define fpos fuuuu
//#define double long double

using namespace std;

int T;
int n, q, i, b[MAXN], f[MAXN];
vector <int> g[MAXN];

struct query{
    int id, a, b, l, r;
} h[MAXN];

int p[20][MAXN], d[MAXN], a[MAXN];
int in[MAXN], out[MAXN], timer;

int dfs(int v){
    int to, i;

    a[timer] = v;
    in[v] = timer++;

    for(i = 1; i < 20; i++)
        p[i][v] = p[i - 1][p[i - 1][v]];

    for(int i = 0; i < g[v].size(); i++){
        int to = g[v][i];

        if(p[0][v] == to)
            continue;

        p[0][to] = v;
        d[to] = d[v] + 1;

        dfs(to);
    }

    a[timer] = v;
    out[v] = timer++;
}

int getLCA(int a, int b){
    int i;

    if(d[a] < d[b])
        swap(a, b);

    for(i = 19; i >= 0; i--){
        if(d[b] - d[a] >= (1 << i))
            a = p[i][a];
    }

    if(a == b)
        return a;

    for(i = 19; i >= 0; i--){
        if(p[i][a] != p[i][b]){
            a = p[i][a];
            b = p[i][b];
        }
    }

    return p[0][a];
}

bool cmp(query x, query y){
    if(x.l / T == y.l / T)
        return x.r < y.r;
    return x.l < y.l;
}

int cnt[MAXN], c[2][MAXN], ans[MAXN], ANS;

int add(int x){
    cnt[x]++;

    if(cnt[x] == 2){
        ANS -= c[b[x] ^ 1][f[x]];
        c[b[x]][f[x]]--;
    }
    else{
        ANS += c[b[x] ^ 1][f[x]];
        c[b[x]][f[x]]++;
    }
}

int del(int x){
    cnt[x]--;

    if(cnt[x] == 1){
        ANS += c[b[x] ^ 1][f[x]];
        c[b[x]][f[x]]++;
    }
    else{
        ANS -= c[b[x] ^ 1][f[x]];
        c[b[x]][f[x]]--;
    }
}

main(){
    //freopen("input.txt", "r", stdin);
    //freopen("output.txt", "w", stdout);

    ios_base::sync_with_stdio(0);
    cin.tie();

    cin >> n;

    for(i = 0; i < n; i++)
        cin >> b[i];

    map <int, int> mp;
    int sz = 0;

    for(i = 0; i < n; i++){
        cin >> f[i];
        if(!mp.count(f[i]))
            mp[f[i]] = sz++;
        f[i] = mp[f[i]];
    }

    for(i = 0; i < n - 1; i++){
        int a, b;
        cin >> a >> b;
        a--; b--;
        g[a].push_back(b);
        g[b].push_back(a);
    }

    dfs(0);

    cin >> q;

    T = sqrt(n);

    for(i = 0; i < n; i++){
        cin >> h[i].a >> h[i].b;
        h[i].a--; h[i].b--;
        h[i].id = i;

        if(in[h[i].a] > in[h[i].b])
            swap(h[i].a, h[i].b);

        h[i].l = in[h[i].a] + 1;
        h[i].r = out[h[i].b] - 1;
    }

    sort(h, h + q, cmp);

    int l = 0, r = -1;

    for(i = 0; i < n; i++){
        while(l < h[i].l){
            del(a[l]);
            l++;
        }

        while(l > h[i].l){
            add(a[l - 1]);
            l--;
        }

        while(r < h[i].r){
            add(a[r + 1]);
            r++;
        }

        while(r > h[i].r){
            del(a[r]);
            r--;
        }

        add(a[in[getLCA(h[i].a, h[i].b)]]);

        ans[h[i].id] = ANS;

        del(a[in[getLCA(h[i].a, h[i].b)]]);
    }

    for(i = 0; i < q; i++)
        cout << ans[i] << endl;
    return 0;
}


#include <iostream>
#include <algorithm>
#include <cstdio>
#include <vector>
#include <cmath>
#include <complex>
#include <queue>
#include <map>
#include <set>
#include <bitset>
#include <iomanip>
#include <ctime>
//#include <unordered_map>
#define ll long long
#define MAXN 1000005
#define INF 1000000000LL
//#define y second
//#define x first
//#define int long long
#define fpos fuuuu
//#define double long double

using namespace std;

int T;
int n, q, i, b[MAXN], f[MAXN];
vector <int> g[MAXN];

struct query{
    int id, a, b, l, r;
} h[MAXN];

int p[20][MAXN], d[MAXN], a[MAXN];
int in[MAXN], out[MAXN], timer;

int dfs(int v){
    int to, i;

    a[timer] = v;
    in[v] = timer++;

    for(i = 1; i < 20; i++)
        p[i][v] = p[i - 1][p[i - 1][v]];

    for(int i = 0; i < g[v].size(); i++){
        int to = g[v][i];

        if(p[0][v] == to)
            continue;

        p[0][to] = v;
        d[to] = d[v] + 1;

        dfs(to);
    }

    a[timer] = v;
    out[v] = timer++;
}

int getLCA(int a, int b){
    int i;

    if(d[a] < d[b])
        swap(a, b);

    for(i = 19; i >= 0; i--){
        if(d[b] - d[a] >= (1 << i))
            a = p[i][a];
    }

    if(a == b)
        return a;

    for(i = 19; i >= 0; i--){
        if(p[i][a] != p[i][b]){
            a = p[i][a];
            b = p[i][b];
        }
    }

    return p[0][a];
}

bool cmp(query x, query y){
    if(x.l / T == y.l / T)
        return x.r < y.r;
    return x.l < y.l;
}

int cnt[MAXN], c[2][MAXN], ans[MAXN], ANS;

int add(int x){
    cnt[x]++;

    if(cnt[x] == 2){
        ANS -= c[b[x] ^ 1][f[x]];
        c[b[x]][f[x]]--;
    }
    else{
        ANS += c[b[x] ^ 1][f[x]];
        c[b[x]][f[x]]++;
    }
}

int del(int x){
    cnt[x]--;

    if(cnt[x] == 1){
        ANS += c[b[x] ^ 1][f[x]];
        c[b[x]][f[x]]++;
    }
    else{
        ANS -= c[b[x] ^ 1][f[x]];
        c[b[x]][f[x]]--;
    }
}

main(){
    //freopen("input.txt", "r", stdin);
    //freopen("output.txt", "w", stdout);

    ios_base::sync_with_stdio(0);
    cin.tie();

    cin >> n;

    for(i = 0; i < n; i++)
        cin >> b[i];

    map <int, int> mp;
    int sz = 0;

    for(i = 0; i < n; i++){
        cin >> f[i];
        if(!mp.count(f[i]))
            mp[f[i]] = sz++;
        f[i] = mp[f[i]];
    }

    for(i = 0; i < n - 1; i++){
        int a, b;
        cin >> a >> b;
        a--; b--;
        g[a].push_back(b);
        g[b].push_back(a);
    }

    dfs(0);

    cin >> q;

    T = sqrt(n);

    for(i = 0; i < n; i++){
        cin >> h[i].a >> h[i].b;
        h[i].a--; h[i].b--;
        h[i].id = i;

        if(in[h[i].a] > in[h[i].b])
            swap(h[i].a, h[i].b);

        h[i].l = in[h[i].a] + 1;
        h[i].r = out[h[i].b] - 1;
    }

    sort(h, h + q, cmp);

    int l = 0, r = -1;

    for(i = 0; i < n; i++){
        while(l < h[i].l){
            del(a[l]);
            l++;
        }

        while(l > h[i].l){
            add(a[l - 1]);
            l--;
        }

        while(r < h[i].r){
            add(a[r + 1]);
            r++;
        }

        while(r > h[i].r){
            del(a[r]);
            r--;
        }

        add(a[in[getLCA(h[i].a, h[i].b)]]);

        ans[h[i].id] = ANS;

        del(a[in[getLCA(h[i].a, h[i].b)]]);
    }

    for(i = 0; i < q; i++)
        cout << ans[i] << endl;
    return 0;
}


#include <iostream>
#include <algorithm>
#include <cstdio>
#include <vector>
#include <cmath>
#include <complex>
#include <queue>
#include <map>
#include <set>
#include <bitset>
#include <iomanip>
#include <ctime>
//#include <unordered_map>
#define ll long long
#define MAXN 200005
#define INF 1000000000LL
//#define y second
//#define x first
//#define int long long
#define fpos fuuuu
//#define double long double

using namespace std;

int T;
int n, q, i, b[MAXN], f[MAXN];
vector <int> g[MAXN];

struct query{
    int id, a, b, l, r;
} h[MAXN];

int p[20][MAXN], d[MAXN], a[MAXN];
int in[MAXN], out[MAXN], timer;

int dfs(int v){
    int to, i;

    a[timer] = v;
    in[v] = timer++;

    for(i = 1; i < 20; i++)
        p[i][v] = p[i - 1][p[i - 1][v]];

    for(i = 0; i < g[v].size(); i++){
        to = g[v][i];

        if(p[0][v] == to)
            continue;

        p[0][to] = v;
        d[to] = d[v] + 1;

        dfs(to);
    }

    a[timer] = v;
    out[v] = timer++;
}

int getLCA(int a, int b){
    int i;

    if(d[a] < d[b])
        swap(a, b);

    for(i = 19; i >= 0; i--){
        if(d[a] - d[b] >= (1 << i))
            a = p[i][a];
    }

    if(a == b)
        return a;

    for(i = 19; i >= 0; i--){
        if(p[i][a] != p[i][b]){
            a = p[i][a];
            b = p[i][b];
        }
    }

    return p[0][a];
}

bool cmp(query x, query y){
    if(x.l / T == y.l / T)
        return x.r < y.r;
    return x.l < y.l;
}

int cnt[MAXN], c[2][MAXN];
ll ans[MAXN], ANS;

int add(int x){
    cnt[x]++;

    if(cnt[x] == 2){
        ANS -= c[b[x] ^ 1][f[x]];
        c[b[x]][f[x]]--;
    }
    else{
        ANS += c[b[x] ^ 1][f[x]];
        c[b[x]][f[x]]++;
    }
}

int del(int x){
    cnt[x]--;

    if(cnt[x] == 1){
        ANS += c[b[x] ^ 1][f[x]];
        c[b[x]][f[x]]++;
    }
    else{
        ANS -= c[b[x] ^ 1][f[x]];
        c[b[x]][f[x]]--;
    }
}

main(){
    //freopen("input.txt", "r", stdin);
    //freopen("output.txt", "w", stdout);

    ios_base::sync_with_stdio(0);
    cin.tie();

    cin >> n;

    for(i = 0; i < n; i++)
        cin >> b[i];

    map <int, int> mp;
    int sz = 0;

    for(i = 0; i < n; i++){
        cin >> f[i];
        if(!mp.count(f[i]))
            mp[f[i]] = sz++;
        f[i] = mp[f[i]];
    }

    for(i = 0; i < n - 1; i++){
        int a, b;
        cin >> a >> b;
        a--; b--;
        g[a].push_back(b);
        g[b].push_back(a);
    }

    dfs(0);

    cin >> q;

    T = sqrt(n);

    for(i = 0; i < q; i++){
        cin >> h[i].a >> h[i].b;
        h[i].a--; h[i].b--;
        h[i].id = i;

        if(in[h[i].a] > in[h[i].b])
            swap(h[i].a, h[i].b);

        if(getLCA(h[i].a, h[i].b) != h[i].a){
            h[i].l = out[h[i].a];
            h[i].r = in[h[i].b];
        }
        else{
            h[i].l = in[h[i].a] + 1;
            h[i].r = in[h[i].b];
        }
    }

    sort(h, h + q, cmp);

    int l = 0, r = -1;

    for(i = 0; i < q; i++){
        if(h[i].l > h[i].r){
            ans[h[i].id] = 0;
            continue;
        }

        while(r < h[i].r){
            add(a[r + 1]);
            r++;
        }

        while(l > h[i].l){
            add(a[l - 1]);
            l--;
        }

        while(l < h[i].l){
            del(a[l]);
            l++;
        }

        while(r > h[i].r){
            del(a[r]);
            r--;
        }

        add(getLCA(h[i].a, h[i].b));

        ans[h[i].id] = ANS;

        del(getLCA(h[i].a, h[i].b));
    }

    for(i = 0; i < q; i++)
        cout << ans[i] << endl;
    return 0;
}


#include<bits/stdc++.h>
#define LL long long
#define LD long double
#define ull unsigned long long
#define fi first
#define se second
#define mk make_pair
#define PLL pair<LL, LL>
#define PLI pair<LL, int>
#define PII pair<int, int>
#define SZ(x) ((int)x.size())
#define ALL(x) (x).begin(), (x).end()
#define fio ios::sync_with_stdio(false); cin.tie(0);

using namespace std;

const int N = 2e5 + 7;
const int inf = 0x3f3f3f3f;
const LL INF = 0x3f3f3f3f3f3f3f3f;
const int mod = 1e9 + 7;
const double eps = 1e-8;
const double PI = acos(-1);

template<class T, class S> inline void add(T& a, S b) {a += b; if(a >= mod) a -= mod;}
template<class T, class S> inline void sub(T& a, S b) {a -= b; if(a < 0) a += mod;}
template<class T, class S> inline bool chkmax(T& a, S b) {return a < b ? a = b, true : false;}
template<class T, class S> inline bool chkmin(T& a, S b) {return a > b ? a = b, true : false;}

const int B = 500;

int n, q, depth[N], f[N], pa[N][20], gender[N];
int in[N], out[N], id[N], idx, op[N];
LL ans[N];
bool flag[N];
int cnt[2][N];

vector<int> oo;
vector<int> G[N];

struct Qus {
    int L, R, lca, id;
    bool operator < (const Qus& rhs) const {
        if(L / B == rhs.L / B) return R < rhs.R;
        return L < rhs.L;
    }
} qus[N];

int l, r; LL ret;

inline void update(int x) {
    ret += op[id[x]] * cnt[gender[id[x]] ^ 1][f[id[x]]];
    cnt[gender[id[x]]][f[id[x]]] += op[id[x]];
    op[id[x]] = -op[id[x]];
}

void dfs(int u, int fa) {
    depth[u] = depth[fa] + 1;
    pa[u][0] = fa;
    for(int i = 1; i < 20; i++)
        pa[u][i] = pa[pa[u][i - 1]][i - 1];
    id[++idx] = u;
    in[u] = idx;
    for(auto& v : G[u]) {
        if(v == fa) continue;
        dfs(v, u);
    }
    id[++idx] = u;
    out[u] = idx;
}

int getLca(int u, int v) {
    if(depth[u] < depth[v]) swap(u, v);
    for(int i = 19; ~i; i--)
        if((depth[u] - depth[v]) >> i & 1)
            u = pa[u][i];
    if(u == v) return u;
    for(int i = 19; ~i; i--)
        if(pa[u][i] != pa[v][i])
            u = pa[u][i], v = pa[v][i];
    return pa[u][0];
}

int main() {
    scanf("%d", &n);
    for(int i = 1; i <= n; i++) scanf("%d", &gender[i]), op[i] = 1;
    for(int i = 1; i <= n; i++) {
        scanf("%d", &f[i]);
        oo.push_back(f[i]);
    }
    for(int i = 1; i < n; i++) {
        int a, b; scanf("%d%d", &a, &b);
        G[a].push_back(b);
        G[b].push_back(a);
    }
    sort(ALL(oo));
    oo.erase(unique(ALL(oo)), oo.end());
    for(int i = 1; i <= n; i++)
        f[i] = lower_bound(ALL(oo), f[i]) - oo.begin();
    dfs(1, 0);
//    puts("");
//    for(int i = 1; i <= idx; i++) printf("%d ", id[i]);
//    puts("");
    scanf("%d", &q);
    for(int i = 1; i <= q; i++) {
        int a, b, lca;
        scanf("%d%d", &a, &b);
        lca = getLca(a, b);
        if(lca == a || lca == b) {
            if(a == lca) qus[i] = Qus{in[a], in[b], a, i};
            else qus[i] = Qus{in[b], in[a], b, i};
        } else {
            if(in[a] < in[b]) qus[i] = Qus{out[a], in[b], lca, i};
            else qus[i] = Qus{out[b], in[a], lca, i};
        }
//        cout << a << " " << b << " " << getLca(a, b) << "###" << endl;
//        cout << qus[i].L << " " << qus[i].R << " " << qus[i].lca << "$$$" << endl;
    }
    l = 1, r = 0, ret = 0;
    sort(qus + 1, qus + 1 + q);
    for(int o = 1; o <= q; o++) {
        int L = qus[o].L, R = qus[o].R, lca = qus[o].lca, who = qus[o].id;
        while(r < R) update(++r);
        while(l > L) update(--l);
        while(r > R) update(r--);
        while(l < L) update(l++);
        if(lca != id[L] && lca != id[R]) ans[who] = ret + cnt[gender[lca] ^ 1][f[lca]];
        else ans[who] = ret;
    }
    for(int i = 1; i <= q; i++) printf("%lld\n", ans[i]);
    return 0;
}

/*
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
1 3
7 5
*/


#include<bits/stdc++.h>
#define LL long long
#define LD long double
#define ull unsigned long long
#define fi first
#define se second
#define mk make_pair
#define PLL pair<LL, LL>
#define PLI pair<LL, int>
#define PII pair<int, int>
#define SZ(x) ((int)x.size())
#define ALL(x) (x).begin(), (x).end()
#define fio ios::sync_with_stdio(false); cin.tie(0);

using namespace std;

const int N = 2e5 + 7;
const int inf = 0x3f3f3f3f;
const LL INF = 0x3f3f3f3f3f3f3f3f;
const int mod = 1e9 + 7;
const double eps = 1e-8;
const double PI = acos(-1);

template<class T, class S> inline void add(T& a, S b) {a += b; if(a >= mod) a -= mod;}
template<class T, class S> inline void sub(T& a, S b) {a -= b; if(a < 0) a += mod;}
template<class T, class S> inline bool chkmax(T& a, S b) {return a < b ? a = b, true : false;}
template<class T, class S> inline bool chkmin(T& a, S b) {return a > b ? a = b, true : false;}

const int B = 500;

int n, q, depth[N], f[N], pa[N][20], gender[N];
int in[N], out[N], id[N], idx, op[N];
LL ans[N];
bool flag[N];
int cnt[2][N];

vector<int> oo;
vector<int> G[N];

struct Qus {
    int L, R, lca, id;
    bool operator < (const Qus& rhs) const {
        if(L / B == rhs.L / B) return R < rhs.R;
        return L < rhs.L;
    }
} qus[N];

int l, r; LL ret;

inline void update(int x) {
    ret += op[id[x]] * cnt[gender[id[x]] ^ 1][f[id[x]]];
    cnt[gender[id[x]]][f[id[x]]] += op[id[x]];
    op[id[x]] = -op[id[x]];
}

void dfs(int u, int fa) {
    depth[u] = depth[fa] + 1;
    pa[u][0] = fa;
    for(int i = 1; i < 20; i++)
        pa[u][i] = pa[pa[u][i - 1]][i - 1];
    id[++idx] = u;
    in[u] = idx;
    for(auto& v : G[u]) {
        if(v == fa) continue;
        dfs(v, u);
    }
    id[++idx] = u;
    out[u] = idx;
}

int getLca(int u, int v) {
    if(depth[u] < depth[v]) swap(u, v);
    for(int i = 19; ~i; i--)
        if((depth[u] - depth[v]) >> i & 1)
            u = pa[u][i];
    if(u == v) return u;
    for(int i = 19; ~i; i--)
        if(pa[u][i] != pa[v][i])
            u = pa[u][i], v = pa[v][i];
    return pa[u][0];
}

int main() {
    scanf("%d", &n);
    for(int i = 1; i <= n; i++) scanf("%d", &gender[i]), op[i] = 1;
    for(int i = 1; i <= n; i++) {
        scanf("%d", &f[i]);
        oo.push_back(f[i]);
    }
    for(int i = 1; i < n; i++) {
        int a, b; scanf("%d%d", &a, &b);
        G[a].push_back(b);
        G[b].push_back(a);
    }
    sort(ALL(oo));
    oo.erase(unique(ALL(oo)), oo.end());
    for(int i = 1; i <= n; i++)
        f[i] = lower_bound(ALL(oo), f[i]) - oo.begin();
    dfs(1, 0);
    puts("");
    for(int i = 1; i <= idx; i++) printf("%d ", id[i]);
    puts("");
    scanf("%d", &q);
    for(int i = 1; i <= q; i++) {
        int a, b, lca;
        scanf("%d%d", &a, &b);
        lca = getLca(a, b);
        if(lca == a || lca == b) {
            if(a == lca) qus[i] = Qus{in[a], in[b], a, i};
            else qus[i] = Qus{in[b], in[a], b, i};
        } else {
            if(in[a] < in[b]) qus[i] = Qus{out[a], in[b], lca, i};
            else qus[i] = Qus{out[b], in[a], lca, i};
        }
//        cout << a << " " << b << " " << getLca(a, b) << "###" << endl;
//        cout << qus[i].L << " " << qus[i].R << " " << qus[i].lca << "$$$" << endl;
    }
    l = 1, r = 0, ret = 0;
    sort(qus + 1, qus + 1 + q);
    for(int o = 1; o <= q; o++) {
        int L = qus[o].L, R = qus[o].R, lca = qus[o].lca, who = qus[o].id;
        while(r < R) update(++r);
        while(l > L) update(--l);
        while(r > R) update(r--);
        while(l < L) update(l++);
        if(lca != id[L] && lca != id[R]) ans[who] = ret + cnt[gender[lca] ^ 1][f[lca]];
        else ans[who] = ret;
    }
    for(int i = 1; i <= q; i++) printf("%lld\n", ans[i]);
    return 0;
}

/*
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
1 3
7 5
*/


#include <iostream>
#include <cstdio>
#include <algorithm>
#include <vector>
#include <queue>
#include <deque>
#include <list>
#include <map>
#include <set>
#include <cmath>
#include <cstring>
#include <string>
#include <bitset>
#include <fstream>
#include <iomanip>

using namespace std;

typedef long long ll;
typedef double db;
typedef vector<int> vi;
typedef vector<long long> vll;
typedef pair<int,int> pii;
typedef pair<ll,ll> pll;
typedef pair<double,double> pdd;
typedef vector<pii> vii;

#define INF 1000000007ll
#define PB push_back
#define MP make_pair
#define X first
#define Y second
#define cil(a,b) ( ((a)%(b) == 0)?((a)/(b)):((a)/(b)+1) )
#define err(x) cerr << #x << " = " << x << endl;
#define SIZE 100010

int tm = 1, b[SIZE], f[SIZE], st[SIZE], en[SIZE], idx[SIZE], sq, pres[SIZE] = {0};
ll num[SIZE][2], res[SIZE];
vector<int> base, adj[SIZE];
map<int, int> mp;
pair<int, int> q[SIZE];

void dfs (int v, int p) {
   st[v] = tm++;
   base.PB(v);
   for (int i = 0 ; i < adj[v].size() ; ++i) {
      int t = adj[v][i];
      if (t == p) continue;
      dfs (t, v);
   }
   en[v] = tm++;
   base.PB(v);
}

bool compr (int i, int j) {
   if (q[i].X / sq != q[j].X / sq) return (q[i].X / sq < q[j].X / sq);
   return q[i].Y < q[j].Y;
}

int main() {
   base.PB(0);
   int n;
   scanf("%d", &n);
   for (int i = 1 ; i <= n ; ++i) scanf("%d", b + i);
   for (int i = 1 ; i <= n ; ++i) {
      scanf("%d", f + i);
      mp[f[i]];
   }
   int k = 0;
   for (map<int, int>::iterator it = mp.begin() ; it != mp.end() ; ++it) {
      it->Y = k++;
   }
   for (int i = 1 ; i <= n ; ++i) {
      f[i] = mp[f[i]];
   }
   for (int i = 1 ; i < n ; ++i) {
      int u, v;
      scanf("%d %d", &u, &v);
      adj[u].PB(v);
      adj[v].PB(u);
   }
   dfs (1, 1);
   sq = sqrt(base.size() - 1);

   int Q;
   scanf("%d", &Q);
   for (int i = 0 ; i < Q ; ++i) {
      scanf("%d %d", &q[i].X, &q[i].Y);
      if (st[q[i].X] > st[q[i].Y]) swap(q[i].X, q[i].Y);
      q[i].X = (en[q[i].X] < st[q[i].Y]) ? en[q[i].X] : st[q[i].X];
      q[i].Y = st[q[i].Y];
      idx[i] = i;
   }
   sort (idx, idx + Q, compr);

   int currL = 0, currR = 0;
   ll ans = 0;
   for (int i = 0 ; i < Q ; ++i) {
      int u = q[idx[i]].X, v = q[idx[i]].Y;
      while (currR < v) {
         ++currR;
         int no = base[currR];
         int cnt = ++pres[no];
         if (cnt & 1) {
            ans += num[f[no]][b[no] ^ 1];
            ++num[f[no]][b[no]];
         }
         else {
            ans -= num[f[no]][b[no] ^ 1];
            --num[f[no]][b[no]];
         }
      }

      while (currR > v) {
         int no = base[currR];
         int cnt = --pres[no];
         if (cnt & 1) {
            ans += num[f[no]][b[no] ^ 1];
            ++num[f[no]][b[no]];
         }
         else {
            ans -= num[f[no]][b[no] ^ 1];
            --num[f[no]][b[no]];
         }
         --currR;
      }

      while (currL > u) {
         --currL;
         int no = base[currL];
         int cnt = ++pres[no];
         if (cnt & 1) {
            ans += num[f[no]][b[no] ^ 1];
            ++num[f[no]][b[no]];
         }
         else {
            ans -= num[f[no]][b[no] ^ 1];
            --num[f[no]][b[no]];
         }
      }

      while (currL < u) {
         int no = base[currL];
         int cnt = --pres[no];
         if (cnt & 1) {
            ans += num[f[no]][b[no] ^ 1];
            ++num[f[no]][b[no]];
         }
         else {
            ans -= num[f[no]][b[no] ^ 1];
            --num[f[no]][b[no]];
         }
         ++currL;
      }

      res[idx[i]] = ans;
   }

   for (int i = 0 ; i < Q ; ++i) printf("%lld\n", res[i]);

   return 0;
}


#include <iostream>
#include <cstdio>
#include <algorithm>
#include <vector>
#include <queue>
#include <deque>
#include <list>
#include <map>
#include <set>
#include <cmath>
#include <cstring>
#include <string>
#include <bitset>
#include <fstream>
#include <iomanip>

using namespace std;

typedef long long ll;
typedef double db;
typedef vector<int> vi;
typedef vector<long long> vll;
typedef pair<int,int> pii;
typedef pair<ll,ll> pll;
typedef pair<double,double> pdd;
typedef vector<pii> vii;

#define INF 1000000007ll
#define PB push_back
#define MP make_pair
#define X first
#define Y second
#define cil(a,b) ( ((a)%(b) == 0)?((a)/(b)):((a)/(b)+1) )
#define err(x) cerr << #x << " = " << x << endl;
#define SIZE 100010
#define LN 18

int tmm = 1, b[SIZE], f[SIZE], st[SIZE], en[SIZE], idx[SIZE], sq, pres[SIZE] = {0};
int par[SIZE][LN], d[SIZE] = {0};
ll num[SIZE][2], res[SIZE];
vector<int> base, adj[SIZE];
map<int, int> mp;
pair<int, int> q[SIZE];

void dfs (int v, int p) {
   st[v] = tmm++;
   d[v] = d[p] + 1;
   base.PB(v);
   par[v][0] = p;
   for (int i = 1 ; i < LN ; ++i) {
      if ((1 << i) <= d[v]) par[v][i] = par[par[v][i - 1]][i - 1];
      else par[v][i] = 0;
   }
   for (int i = 0 ; i < adj[v].size() ; ++i) {
      int t = adj[v][i];
      if (t == p) continue;
      dfs (t, v);
   }
   base.PB(v);
   en[v] = tmm++;
}

int LCA (int u, int v) {
   if (d[u] < d[v]) swap(u, v);
   int diff = d[u] - d[v];
   for (int i = 0 ; (1 << i) <= diff ; ++i) {
      if (diff & (1 << i)) {
         u = par[u][i];
      }
   }
   if (u == v) return u;
   for (int i = LN - 1 ; i >= 0 ; --i) {
      if (par[u][i] != par[v][i]) {
         u = par[u][i];
         v = par[v][i];
      }
   }
   return par[u][0];
}

bool compr (int i, int j) {
   if (q[i].X / sq != q[j].X / sq) return (q[i].X / sq < q[j].X / sq);
   return q[i].Y < q[j].Y;
}

int main() {
   base.PB(0);
   int n;
   scanf("%d", &n);
   for (int i = 1 ; i <= n ; ++i) scanf("%d", b + i);
   for (int i = 1 ; i <= n ; ++i) {
      scanf("%d", f + i);
      mp[f[i]];
   }
   int k = 1;
   for (map<int, int>::iterator it = mp.begin() ; it != mp.end() ; ++it) {
      it->Y = k++;
   }
   for (int i = 1 ; i <= n ; ++i) {
      f[i] = mp[f[i]];
   }
   for (int i = 1 ; i < n ; ++i) {
      int u, v;
      scanf("%d %d", &u, &v);
      adj[u].PB(v);
      adj[v].PB(u);
   }
   d[0] = -1;
   dfs (1, 0);
   sq = sqrt(base.size() - 1);

   int Q;
   scanf("%d", &Q);
   for (int i = 0 ; i < Q ; ++i) {
      scanf("%d %d", &q[i].X, &q[i].Y);
      if (st[q[i].X] > st[q[i].Y]) swap(q[i].X, q[i].Y);
      q[i].X = (en[q[i].X] < st[q[i].Y]) ? en[q[i].X] : st[q[i].X];
      q[i].Y = st[q[i].Y];
      idx[i] = i;
   }
   sort (idx, idx + Q, compr);

   int currL = 1, currR = 0;
   ll ans = 0;
   for (int i = 0 ; i < Q ; ++i) {
      int u = q[idx[i]].X, v = q[idx[i]].Y;
      int lca = LCA(base[u], base[v]);
      while (currR < v) {
         ++currR;
         int no = base[currR];
         int cnt = ++pres[no];
         if (cnt & 1) {
            ans += num[f[no]][b[no] ^ 1];
            ++num[f[no]][b[no]];
         }
         else {
            ans -= num[f[no]][b[no] ^ 1];
            --num[f[no]][b[no]];
         }
      }

      while (currR > v) {
         int no = base[currR];
         int cnt = --pres[no];
         if (cnt & 1) {
            ans += num[f[no]][b[no] ^ 1];
            ++num[f[no]][b[no]];
         }
         else {
            ans -= num[f[no]][b[no] ^ 1];
            --num[f[no]][b[no]];
         }
         --currR;
      }

      while (currL > u) {
         --currL;
         int no = base[currL];
         int cnt = ++pres[no];
         if (cnt & 1) {
            ans += num[f[no]][b[no] ^ 1];
            ++num[f[no]][b[no]];
         }
         else {
            ans -= num[f[no]][b[no] ^ 1];
            --num[f[no]][b[no]];
         }
      }

      while (currL < u) {
         int no = base[currL];
         int cnt = --pres[no];
         if (cnt & 1) {
            ans += num[f[no]][b[no] ^ 1];
            ++num[f[no]][b[no]];
         }
         else {
            ans -= num[f[no]][b[no] ^ 1];
            --num[f[no]][b[no]];
         }
         ++currL;
      }

      res[idx[i]] = ans + ((lca != base[u]) ? num[f[lca]][b[lca] ^ 1] : 0);
   }

   for (int i = 0 ; i < Q ; ++i) printf("%lld\n", res[i]);

   return 0;
}


#include <iostream>
#include <cstdio>
#include <algorithm>
#include <vector>
#include <queue>
#include <deque>
#include <list>
#include <map>
#include <set>
#include <cmath>
#include <cstring>
#include <string>
#include <bitset>
#include <fstream>
#include <iomanip>

using namespace std;

typedef long long ll;
typedef double db;
typedef vector<int> vi;
typedef vector<long long> vll;
typedef pair<int,int> pii;
typedef pair<ll,ll> pll;
typedef pair<double,double> pdd;
typedef vector<pii> vii;

#define INF 1000000007ll
#define PB push_back
#define MP make_pair
#define X first
#define Y second
#define cil(a,b) ( ((a)%(b) == 0)?((a)/(b)):((a)/(b)+1) )
#define err(x) cerr << #x << " = " << x << endl;
#define SIZE 100010

int tmm = 1, b[SIZE], f[SIZE], st[SIZE], en[SIZE], idx[SIZE], sq, pres[SIZE] = {0};
ll num[SIZE][2], res[SIZE];
vector<int> base, adj[SIZE];
map<int, int> mp;
pair<int, int> q[SIZE];

void dfs (int v, int p) {
   st[v] = tmm++;
   base.PB(v);
   for (int i = 0 ; i < adj[v].size() ; ++i) {
      int t = adj[v][i];
      if (t == p) continue;
      dfs (t, v);
   }
   en[v] = tmm++;
   base.PB(v);
}

bool compr (int i, int j) {
   if (q[i].X / sq != q[j].X / sq) return (q[i].X / sq < q[j].X / sq);
   return q[i].Y < q[j].Y;
}

int main() {
   base.PB(0);
   int n;
   scanf("%d", &n);
   for (int i = 1 ; i <= n ; ++i) scanf("%d", b + i);
   for (int i = 1 ; i <= n ; ++i) {
      scanf("%d", f + i);
      mp[f[i]];
   }
   int k = 1;
   for (map<int, int>::iterator it = mp.begin() ; it != mp.end() ; ++it) {
      it->Y = k++;
   }
   for (int i = 1 ; i <= n ; ++i) {
      f[i] = mp[f[i]];
   }
   for (int i = 1 ; i < n ; ++i) {
      int u, v;
      scanf("%d %d", &u, &v);
      adj[u].PB(v);
      adj[v].PB(u);
   }
   dfs (1, 1);
   sq = sqrt(base.size() - 1);

   int Q;
   scanf("%d", &Q);
   for (int i = 0 ; i < Q ; ++i) {
      scanf("%d %d", &q[i].X, &q[i].Y);
      if (st[q[i].X] > st[q[i].Y]) swap(q[i].X, q[i].Y);
      q[i].X = (en[q[i].X] < st[q[i].Y]) ? en[q[i].X] : st[q[i].X];
      q[i].Y = st[q[i].Y];
      idx[i] = i;
   }
   sort (idx, idx + Q, compr);

   int currL = 0, currR = 0;
   ll ans = 0;
   for (int i = 0 ; i < Q ; ++i) {
      int u = q[idx[i]].X, v = q[idx[i]].Y;
      while (currR < v) {
         ++currR;
         int no = base[currR];
         int cnt = ++pres[no];
         if (cnt & 1) {
            ans += num[f[no]][b[no] ^ 1];
            ++num[f[no]][b[no]];
         }
         else {
            ans -= num[f[no]][b[no] ^ 1];
            --num[f[no]][b[no]];
         }
      }

      while (currR > v) {
         int no = base[currR];
         int cnt = --pres[no];
         if (cnt & 1) {
            ans += num[f[no]][b[no] ^ 1];
            ++num[f[no]][b[no]];
         }
         else {
            ans -= num[f[no]][b[no] ^ 1];
            --num[f[no]][b[no]];
         }
         --currR;
      }

      while (currL > u) {
         --currL;
         int no = base[currL];
         int cnt = ++pres[no];
         if (cnt & 1) {
            ans += num[f[no]][b[no] ^ 1];
            ++num[f[no]][b[no]];
         }
         else {
            ans -= num[f[no]][b[no] ^ 1];
            --num[f[no]][b[no]];
         }
      }

      while (currL < u) {
         int no = base[currL];
         int cnt = --pres[no];
         if (cnt & 1) {
            ans += num[f[no]][b[no] ^ 1];
            ++num[f[no]][b[no]];
         }
         else {
            ans -= num[f[no]][b[no] ^ 1];
            --num[f[no]][b[no]];
         }
         ++currL;
      }

      res[idx[i]] = ans;
   }

   for (int i = 0 ; i < Q ; ++i) printf("%lld\n", res[i]);

   return 0;
}


#include <iostream>
#include <cstdio>
#include <algorithm>
#include <vector>
#include <queue>
#include <deque>
#include <list>
#include <map>
#include <set>
#include <cmath>
#include <cstring>
#include <string>
#include <bitset>
#include <fstream>
#include <iomanip>

using namespace std;

typedef long long ll;
typedef double db;
typedef vector<int> vi;
typedef vector<long long> vll;
typedef pair<int,int> pii;
typedef pair<ll,ll> pll;
typedef pair<double,double> pdd;
typedef vector<pii> vii;

#define INF 1000000007ll
#define PB push_back
#define MP make_pair
#define X first
#define Y second
#define cil(a,b) ( ((a)%(b) == 0)?((a)/(b)):((a)/(b)+1) )
#define err(x) cerr << #x << " = " << x << endl;
#define SIZE 100010

int tmm = 1, b[SIZE], f[SIZE], st[SIZE], en[SIZE], idx[SIZE], sq, pres[SIZE] = {0};
ll num[SIZE][2], res[SIZE];
vector<int> base, adj[SIZE];
map<int, int> mp;
pair<int, int> q[SIZE];

void dfs (int v, int p) {
   st[v] = tmm++;
   base.PB(v);
   for (int i = 0 ; i < adj[v].size() ; ++i) {
      int t = adj[v][i];
      if (t == p) continue;
      dfs (t, v);
   }
   en[v] = tmm++;
   base.PB(v);
}

bool compr (int i, int j) {
   if (q[i].X / sq != q[j].X / sq) return (q[i].X / sq < q[j].X / sq);
   return q[i].Y < q[j].Y;
}

int main() {
   base.PB(0);
   int n;
   scanf("%d", &n);
   for (int i = 1 ; i <= n ; ++i) scanf("%d", b + i);
   for (int i = 1 ; i <= n ; ++i) {
      scanf("%d", f + i);
      mp[f[i]];
   }
   int k = 0;
   for (map<int, int>::iterator it = mp.begin() ; it != mp.end() ; ++it) {
      it->Y = k++;
   }
   for (int i = 1 ; i <= n ; ++i) {
      f[i] = mp[f[i]];
   }
   for (int i = 1 ; i < n ; ++i) {
      int u, v;
      scanf("%d %d", &u, &v);
      adj[u].PB(v);
      adj[v].PB(u);
   }
   dfs (1, 1);
   sq = sqrt(base.size() - 1);

   int Q;
   scanf("%d", &Q);
   for (int i = 0 ; i < Q ; ++i) {
      scanf("%d %d", &q[i].X, &q[i].Y);
      if (st[q[i].X] > st[q[i].Y]) swap(q[i].X, q[i].Y);
      q[i].X = (en[q[i].X] < st[q[i].Y]) ? en[q[i].X] : st[q[i].X];
      q[i].Y = st[q[i].Y];
      idx[i] = i;
   }
   sort (idx, idx + Q, compr);

   int currL = 0, currR = 0;
   ll ans = 0;
   for (int i = 0 ; i < Q ; ++i) {
      int u = q[idx[i]].X, v = q[idx[i]].Y;
      while (currR < v) {
         ++currR;
         int no = base[currR];
         int cnt = ++pres[no];
         if (cnt & 1) {
            ans += num[f[no]][b[no] ^ 1];
            ++num[f[no]][b[no]];
         }
         else {
            ans -= num[f[no]][b[no] ^ 1];
            --num[f[no]][b[no]];
         }
      }

      while (currR > v) {
         int no = base[currR];
         int cnt = --pres[no];
         if (cnt & 1) {
            ans += num[f[no]][b[no] ^ 1];
            ++num[f[no]][b[no]];
         }
         else {
            ans -= num[f[no]][b[no] ^ 1];
            --num[f[no]][b[no]];
         }
         --currR;
      }

      while (currL > u) {
         --currL;
         int no = base[currL];
         int cnt = ++pres[no];
         if (cnt & 1) {
            ans += num[f[no]][b[no] ^ 1];
            ++num[f[no]][b[no]];
         }
         else {
            ans -= num[f[no]][b[no] ^ 1];
            --num[f[no]][b[no]];
         }
      }

      while (currL < u) {
         int no = base[currL];
         int cnt = --pres[no];
         if (cnt & 1) {
            ans += num[f[no]][b[no] ^ 1];
            ++num[f[no]][b[no]];
         }
         else {
            ans -= num[f[no]][b[no] ^ 1];
            --num[f[no]][b[no]];
         }
         ++currL;
      }

      res[idx[i]] = ans;
   }

   for (int i = 0 ; i < Q ; ++i) printf("%lld\n", res[i]);

   return 0;
}