#include <bits/stdc++.h>
using namespace std::literals::string_literals;
using i64 = std::int_fast64_t;
using std::cout;
using std::cerr;
using std::endl;
using std::cin;

template<typename T>
std::vector<T> make_v(size_t a){return std::vector<T>(a);}

template<typename T,typename... Ts>
auto make_v(size_t a,Ts... ts){
  return std::vector<decltype(make_v<T>(ts...))>(a,make_v<T>(ts...));
}

int main() {
	int n; scanf("%d", &n);
	std::vector<int> a(n), c(n);
	std::vector<i64> b(n), d(n);
	for(int i = 0; i < n; i++) scanf("%d", &a[i]);
	for(int i = 0; i < n; i++) scanf("%d", &c[i]);
	for(int i = 0; i < n; i++) scanf("%lld", &b[i]);
	for(int i = 0; i < n; i++) scanf("%lld", &d[i]);

	bool possible = true;
	auto ans = make_v<int>(n, n, 63);
	for(int i = 0; i < n; i++) {
		for(int j = 0; j < n; j++) {
			for(int k = 0; k < 63; k++) {
				int bit = b[i] >> k & 1;

				if(!a[i]) {
					if(bit) ans[i][j][k] = 1;
					else ans[i][j][k] = 2;
				} else {
					if(!bit) ans[i][j][k] = 0;
					else ans[i][j][k] = 2;
				}
			}
		}
	}

	for(int j = 0; j < n; j++) {
		for(int i = 0; i < n; i++) {
			for(int k = 0; k < 63; k++) {
				int bit = d[j] >> k & 1;

				if(!c[j]) {
					if(bit and ans[i][j][k] == 0) possible = false;
					if(bit) ans[i][j][k] = 1;
				} else {
					if(!bit and ans[i][j][k] == 1) possible = false;
					if(!bit) ans[i][j][k] = 0;
				}
			}
		}
	}

	for(int k = 0; k < 63; k++) {
		bool exist = false;
		std::vector<int> x(n), y(n);
		for(int i = 0; i < n; i++) {
			for(int j = 0; j < n; j++) {
				if(ans[i][j][k] != 2) continue;
				if(a[i] != c[j]) continue;

				ans[i][j][k] = a[i];
				x[i] = y[j] = true;
				exist = true;
			}
		}
		if(exist) continue;
		
		for(int i = 0; i < n; i++) for(int j = 0; j < n; j++) x[i] += (ans[i][j][k] == 2);
		for(int j = 0; j < n; j++) for(int i = 0; i < n; i++) y[j] += (ans[i][j][k] == 2);

		std::vector<int> X(n), Y(n);
		using P = std::tuple<int, int, int>;
		std::priority_queue<P, std::vector<P>, std::greater<P>> qu;
		for(int i = 0; i < n; i++) {
			qu.push({x[i], 0, i});
			qu.push({y[i], 1, i});
		}
		while(!qu.empty()) {
			auto [A, B, C] = qu.top(); qu.pop();
			if(!B and X[C]) continue;
			if(B and Y[C]) continue;

			if(!B) {
				for(int j = 0; j < n; j++) {
					if(ans[C][j][k] != 2) continue;
					ans[C][j][k] = a[C];
					y[j]--;
					qu.push({y[j], 1, j});
					break;
				}
			} else {
				for(int i = 0; i < n; i++) {
					if(ans[i][C][k] != 2) continue;
					ans[i][C][k] = 2;
					x[i]--;
					qu.push({x[i], 0, i});
					break;
				}
			}
		}

		for(int i = 0; i < n; i++) for(int j = 0; j < n; j++) if(ans[i][j][k] == 2) ans[i][j][k] = 0;
		for(auto v: X) if(!v) possible = false;
		for(auto v: Y) if(!v) possible = false;
	}

	if(!possible) {
		printf("-1\n");
		return 0;
	}
	
	for(int i = 0; i < n; i++) {
		for(int j = 0; j < n; j++) {
			i64 val = 0;
			for(int k = 0; k < 63; k++) if(ans[i][j][k]) val |= 1LL << k;

			printf("%lld ", val);
		}
		printf("\n");
	}
	return 0;
}
