Logo Wy Online Judge

WyOJ

Paste!

#include <array>
#include <bit>
#include <iostream>
#include <vector>

template<class Uint, int Digits>
struct Xor_basis{
	std::array<Uint, Digits> basis;
	std::array<int, Digits> stamp;
	void insert(Uint num, int time) {
		for(int i = Digits - 1; i >= 0; i--)
		{
			if(!(num >> i & 1))
				continue;
			if(basis[i])
			{
				Uint nxt = basis[i] ^ num;
				if(stamp[i] <= time)
				{
					basis[i] = num;
					std::swap(stamp[i], time);
				}
				num = nxt;
			}
			else
			{
				basis[i] = num;
				stamp[i] = time;
				break;
			}
		}
	}
	bool can_expr(Uint num) const {
		while(num)
		{ 
			int dig{std::bit_width(num) - 1};
			if(!basis[dig])
				return false;
			num ^= basis[dig];
		} 
		return !num;
	}
	Xor_basis()
		:basis{}, stamp()
	{ stamp.fill(-1); }
};

struct Graph{
	unsigned n;
	std::vector<std::vector<unsigned>> table;
	void add_edge(unsigned node1, unsigned node2) {
		table[node1].push_back(node2);
		table[node2].push_back(node1);  
	}
	auto& operator[] (unsigned pos) const {
		return table[pos];
	}
	Graph(unsigned size)
		:n(size), table(size)
	{}
};

class TDeCM{
	unsigned fdss(unsigned node) {
		size[node] = 1;
		hson[node] = None;
		for(auto to : G[node])
			if(to != parent[node])
			{
				parent[to] = node;
				deep[to] = deep[node] + 1;
				size[node] += fdss(to);
				if(hson[node] == None || size[hson[node]] < size[to])
					hson[node] = to;
			}
		return size[node];
	}
	void travel(unsigned node) {
		if(hson[node] == None)
			return;
		top[hson[node]] = top[node];
		travel(hson[node]);
		for(auto to : G[node])
			if(to != parent[node] && to != hson[node])
			{
				top[to] = to;
				travel(to);
			}
	}
public:
	enum { None = 1312537 };
	const Graph& G;
	std::vector<unsigned> parent, deep, size;
	std::vector<unsigned> hson, top;
	unsigned lca(unsigned node1, unsigned node2) {
		while(top[node1] != top[node2])
		{
			if(deep[top[node1]] > deep[top[node2]])
				std::swap(node1, node2);
			node2 = parent[top[node2]];
		}
		if(deep[node1] < deep[node2])
			return node1;
		return node2;
	}
	TDeCM(const Graph& tree, unsigned root)
		:G(tree), parent(tree.n), deep(tree.n),
		size(tree.n), hson(tree.n), top(tree.n) {
		deep[root] = 0;
		parent[root] = root;
		fdss(root);
		top[root] = root;
		travel(root);
	}
};

int main() {
	using namespace std;
	int n;
	cin >> n;
	auto val = new unsigned[n];
	for(int i = 0; i < n; i++)
		cin >> val[i];
	Graph G(n);
	for(int i = 1; i < n; i++)
	{
		int u, v;
		cin >> u >> v;
		G.add_edge(u - 1, v - 1);
	}
	
	TDeCM lca(G, 0);
	auto path_xor = new Xor_basis<unsigned, 20>[n];
	auto proc_basis = [&] (unsigned node, auto&& self) -> void {
		path_xor[node].insert(val[node], lca.deep[node]);
		for(auto to : G[node])
			if(to != lca.parent[node])
			{
				path_xor[to] = path_xor[node];
				self(to, self);
			}
	};
	proc_basis(0, proc_basis);
	
	int q;
	cin >> q;
	while(q--)
	{
		int x, y, k;
		cin >> x >> y >> k;
		--x;
		--y;
		int lca_deep = lca.deep[lca.lca(x, y)];
		Xor_basis<unsigned, 20> path;
		for(int i = 19; i >= 0; i--)
		{
			if(path_xor[x].stamp[i] >= lca_deep)
				path.insert(path_xor[x].basis[i], 0);
			if(path_xor[y].stamp[i] >= lca_deep)
				path.insert(path_xor[y].basis[i], 0); 
		} 
		if(path.can_expr(k))
			cout << "YES" << endl;
		else
			cout << "NO" << endl; 
	}
	delete[] path_xor; 
	delete[] val;
	return 0;
}