Problem:
Score : 1800 points

Problem Statement

Given are integer sequences A and B of length 3N. Each of these two sequences contains three copies of each of 1, 2, \dots, N.
In other words, A and B are both arrangements of (1, 1, 1, 2, 2, 2, \dots, N, N, N).

Tak can perform the following operation to the sequence A arbitrarily many times:

Pick a value from 1, 2, \dots, N and call it x. A contains exactly three copies of x. Remove the middle element of these three. After that, append x to the beginning or the end of A.

Check if he can turn A into B. If he can, print the minimum required number of operations to achieve that.

Constraints

1 \leq N \leq 33

A and B are both arrangements of (1, 1, 1, 2, 2, 2, \dots, N, N, N).

All values in input are integers.

Input

Input is given from Standard Input in the following format:

N
A_1 A_2 ... A_{3N}
B_1 B_2 ... B_{3N}

Output

If Tak can turn A into B, print the minimum required number of operations to achieve that. Otherwise, print -1.

Sample Input 1

3
2 3 1 1 3 2 2 1 3
1 2 2 3 1 2 3 1 3

Sample Output 1

4

For example, Tak can perform operations as follows:

2 3 1 1 3 2 2 1 3 (The initial state)

2 2 3 1 1 3 2 1 3 (Pick x = 2 and append it to the beginning)

2 2 3 1 3 2 1 3 1 (Pick x = 1 and append it to the end)

1 2 2 3 1 3 2 3 1 (Pick x = 1 and append it to the beginning)

1 2 2 3 1 2 3 1 3 (Pick x = 3 and append it to the end)

Sample Input 2

3
1 1 1 2 2 2 3 3 3
1 1 1 2 2 2 3 3 3

Sample Output 2

0

Sample Input 3

3
2 3 3 1 1 1 2 2 3
3 2 2 1 1 1 3 3 2

Sample Output 3

-1

Sample Input 4

8
3 6 7 5 4 8 4 1 1 3 8 7 3 8 2 4 7 5 2 2 6 5 6 1
7 5 8 1 3 6 7 5 4 8 1 3 3 8 2 4 2 6 5 6 1 4 7 2

Sample Output 4

7

Solution in C++ (GCC 9.2.1 with AC Library v1.1) (judge verdict: Wrong Answer)

#include<iostream>
#include<string>
#include<cstdio>
#include<vector>
#include<cmath>
#include<algorithm>
#include<functional>
#include<iomanip>
#include<queue>
#include<ciso646>
#include<random>
#include<map>
#include<set>
#include<bitset>
#include<stack>
#include<unordered_map>
#include<utility>
#include<cassert>
#include<complex>
#include<numeric>
#include<array>
using namespace std;

//#define int long long
typedef long long ll;

typedef unsigned long long ul;
typedef unsigned int ui;
constexpr ll mod = 998244353;
const ll INF = mod * mod;
typedef pair<int, int>P;
#define stop char nyaa;cin>>nyaa;
#define rep(i,n) for(int i=0;i<n;i++)
#define per(i,n) for(int i=n-1;i>=0;i--)
#define Rep(i,sta,n) for(int i=sta;i<n;i++)
#define rep1(i,n) for(int i=1;i<=n;i++)
#define per1(i,n) for(int i=n;i>=1;i--)
#define Rep1(i,sta,n) for(int i=sta;i<=n;i++)
#define all(v) (v).begin(),(v).end()
typedef pair<ll, ll> LP;
typedef long double ld;
typedef pair<ld, ld> LDP;
const ld eps = 1e-12;
const ld pi = acosl(-1.0);

ll mod_pow(ll x, ll n, ll m = mod) {
	ll res = 1;
	while (n) {
		if (n & 1)res = res * x % m;
		x = x * x % m; n >>= 1;
	}
	return res;
}
struct modint {
	ll n;
	modint() :n(0) { ; }
	modint(ll m) :n(m) {
		if (n >= mod)n %= mod;
		else if (n < 0)n = (n % mod + mod) % mod;
	}
	operator int() { return n; }
};
bool operator==(modint a, modint b) { return a.n == b.n; }
modint operator+=(modint& a, modint b) { a.n += b.n; if (a.n >= mod)a.n -= mod; return a; }
modint operator-=(modint& a, modint b) { a.n -= b.n; if (a.n < 0)a.n += mod; return a; }
modint operator*=(modint& a, modint b) { a.n = ((ll)a.n * b.n) % mod; return a; }
modint operator+(modint a, modint b) { return a += b; }
modint operator-(modint a, modint b) { return a -= b; }
modint operator*(modint a, modint b) { return a *= b; }
modint operator^(modint a, ll n) {
	if (n == 0)return modint(1);
	modint res = (a * a) ^ (n / 2);
	if (n % 2)res = res * a;
	return res;
}

ll inv(ll a, ll p) {
	return (a == 1 ? 1 : (1 - p * inv(p % a, a)) / a + p);
}
modint operator/(modint a, modint b) { return a * modint(inv(b, mod)); }

const int max_n = 1 << 21;
modint fact[max_n], factinv[max_n];
void init_f() {
	fact[0] = modint(1);
	for (int i = 0; i < max_n - 1; i++) {
		fact[i + 1] = fact[i] * modint(i + 1);
	}
	factinv[max_n - 1] = modint(1) / fact[max_n - 1];
	for (int i = max_n - 2; i >= 0; i--) {
		factinv[i] = factinv[i + 1] * modint(i + 1);
	}
}
modint comb(int a, int b) {
	if (a < 0 || b < 0 || a < b)return 0;
	return fact[a] * factinv[b] * factinv[a - b];
}

using bt = bitset<100>;
struct graph {
private:
	int n;
	vector<vector<int>> G, rG;
	vector<bool> used;
	vector<int> vs;

	int mk;
	vector<vector<int>> fG;
	vector<vector<int>> ori;
	vector<int> trans;
public:
	graph(int sz) {
		n = sz;
		G.resize(n);
		rG.resize(n);
		used.resize(n);

		fG.resize(n);
		trans.resize(n, -1);
		ori.resize(n);
	}
	void add_edge(int a, int b) {
		G[a].push_back(b);
		rG[b].push_back(a);
	}
	void dfs(int v) {
		used[v] = true;
		rep(i, G[v].size()) {
			if (!used[G[v][i]])dfs(G[v][i]);
		}
		vs.push_back(v);
	}
	void rdfs(int v, int k) {
		used[v] = true;
		queue<int> q; q.push(v);
		vector<int> c;
		while (!q.empty()) {
			int id = q.front(); q.pop();
			ori[k].push_back(id);
			rep(j, rG[id].size()) {
				int to = rG[id][j];
				if (used[to]) {
					if (trans[to] >= 0)c.push_back(trans[to]);
					continue;
				}
				used[to] = true; q.push(to);
			}
		}
		sort(c.begin(), c.end());
		int len = unique(c.begin(), c.end()) - c.begin();
		rep(i, len) {
			fG[c[i]].push_back(k);
		}
		rep(i, ori[k].size()) {
			trans[ori[k][i]] = k;
		}
	}
	void scc() {
		fill(used.begin(), used.end(), false);
		rep(i, n) {
			if (!used[i])dfs(i);
		}
		fill(used.begin(), used.end(), false);
		int k = 0;
		per(i, (int)vs.size()) {
			if (!used[vs[i]]) {
				rdfs(vs[i], k); k++;
			}
		}
		mk = k;
	}
	bool valid() {
		rep(i, mk)if (ori[i].size() > 1)return false;
		return true;
	}
	vector<bt> query() {
		vector<bt> res(n);
		per(i, mk) {
			int id = ori[i][0];
			res[id][id] = 1;
			for (int tto : fG[i]) {
				int to = ori[tto][0];
				res[id] |= res[to];

			}
		}
		return res;
	}
	bool valid(int sz, vector<int> banlist, vector<bool> als) {
		vector<bool> used(sz);
		vector<bool> exi(mk, true);
		per(i, mk) {
			for (int id : ori[i]) {
				if (id < sz) {
					if (banlist[id] & 1)exi[i] = false;
				}
				else {
					if (banlist[id - sz] & 2)exi[i] = false;
				}
				if (used[id % sz])exi[i] = false;
			}
			for (int to : fG[i])if (!exi[to])exi[i] = false;
			if (exi[i]) {
				for (int id : ori[i]) {
					used[id % sz] = true;
				}
			}
		}
		rep(i, als.size())if (als[i] && !used[i])return false;
		return true;
	}
};

int gcd(int a, int b) {
	if (a > b)swap(a, b);
	while (b > 0) {
		int r = a % b; a = b; b = r;
	}
	return a;
}
int gcm(int a, int b) {
	return (a / gcd(a, b)) * b;
}

vector<int> cnt;
vector<int> loc;
void solve() {
	int n; cin >> n;
	vector<int> a(3 * n), b(3 * n);
	rep(i, 3 * n) {
		cin >> a[i]; a[i]--;
	}
	rep(i, 3 * n) {
		cin >> b[i]; b[i]--;
	}
	vector<vector<int>>trans(n, vector<int>(3, -1));
	vector<vector<int>> transb(n, vector<int>(3, -1));
	rep(i, 3 * n) {
		rep(j, 3) {
			if (trans[a[i]][j] < 0) {
				trans[a[i]][j] = i; break;
			}
		}
		rep(j, 3) {
			if (transb[b[i]][j] < 0) {
				transb[b[i]][j] = i; break;
			}
		}
	}
	cnt.resize(n);
	loc.resize(3 * n);
	vector<int> lcnt(n), rcnt(n);
	int ans = mod;
	//[l,r]を残す
	for (int l = 0; l < 3 * n; l++)for (int r = l; r < 3 * n; r++) {
		fill(all(lcnt), 0);
		fill(all(rcnt), 0);
		rep(i, l)lcnt[b[i]]++;
		Rep(i, r + 1, 3 * n) {
			rcnt[b[i]]++;
		}
		rep(i, 3 * n)Rep(j, i, 3 * n) {
			if (a[i] == b[l] && a[j] == b[r]) {
				fill(all(cnt), 0);
				for (int x = l; x <= r; x++) {
					cnt[b[x]]++;
				}
				fill(all(loc), -1);
				bool valid = true;
				graph sc(3 * n);
				rep(x, l - 1) {
					sc.add_edge(x, x + 1);
				}
				for (int x = 3 * n - 1; x - 1 > r; x--) {
					sc.add_edge(x, x - 1);
				}
				rep(c, n) {
					if (cnt[c] == 3) {
						rep(t, 3) {
							loc[transb[c][t]] = trans[c][t];
						}
					}
					else if (cnt[c] == 2) {
						int id = 0;
						rep(t, 3) {
							if (transb[c][t] >= l && transb[c][t] <= r) {
								loc[transb[c][t]] = trans[c][id];
								if (id == 0)id = 2;
							}
						}
					}
					else if (cnt[c] == 1) {
						if (lcnt[c] == 2) {
							loc[transb[c][2]] = trans[c][2];
						}
						else if (rcnt[c] == 2) {
							//cout << transb[c][0] << " " << trans[c][0] << "\n";
							loc[transb[c][0]] = trans[c][0];
						}
						else {
							//
						}
					}
					else {
						if (lcnt[c] == 3) {
							valid = false;
						}
						else if (rcnt[c] == 3) {
							valid = false;
						}
						else {
							if (lcnt[c] == 1) {
								sc.add_edge(transb[c][2], transb[c][0]);
								sc.add_edge(transb[c][0], transb[c][1]);
							}
							else {
								sc.add_edge(transb[c][0], transb[c][2]);
								sc.add_edge(transb[c][2], transb[c][1]);
							}
						}
					}
				}
				if (!valid)continue;
				//scc
				sc.scc();
				if (!sc.valid())continue;


				vector<bt> cp = sc.query();
				graph nw(2 * n);
				vector<int> banlist(n, 0);
				for (int x = l; x <= r; x++) {
					if (loc[x] < 0) {
						int id = b[x];

						int le = -mod;
						if (x - 1 >= l && loc[x - 1] >= 0)le = loc[x - 1];
						int ri = mod;
						if (x + 1 <= r && loc[x + 1] >= 0)ri = loc[x + 1];
						int al = trans[id][0];
						int ar = trans[id][2];
						if (x == l && al != i)banlist[id] |= 1;
						if (x == r && al != j)banlist[id] |= 1;
						if (x == l && ar != i)banlist[id] |= 2;
						if (x == r && ar != j)banlist[id] |= 2;
						if (al < le || al > ri)banlist[id] |= 1;
						if (ar < le || ar > ri)banlist[id] |= 2;
						if (banlist[id] == 3) {
							valid = false;
						}
					}
				}
				if (!valid)continue;
				if (loc[l] >= 0 && loc[l] != i)valid = false;
				if (loc[r] >= 0 && loc[r] != j)valid = false;
				for (int x = l; x < r; x++) {
					if (loc[x] >= 0 && loc[x + 1] >= 0) {
						if (loc[x] > loc[x + 1])valid = false;
					}
				}
				//cout << "? " << l << " " << r << "\n";
				if (!valid)continue;
				for (int x = l; x < r; x++) {
					if (loc[x] < 0 && loc[x + 1] < 0) {
						int al = trans[b[x]][0];
						int ar = trans[b[x]][2];
						int bl = trans[b[x + 1]][0];
						int br = trans[b[x + 1]][2];
						if (al > br) {
							valid = false;
							break;
						}
						if (ar > br) {
							banlist[b[x]] |= 2;
						}
						if (al > bl) {
							banlist[b[x + 1]] |= 1;
						}
						if (ar > bl) {
							nw.add_edge(b[x] + n, b[x + 1] + n);
							nw.add_edge(b[x + 1], b[x]);
						}
					}
				}
				for (int x = l; x <= r; x++) {
					if (loc[x] >= 0)continue;
					int ale = transb[b[x]][0];
					int ari = transb[b[x]][2];
					if (cp[ari][ale])banlist[b[x]] |= 1;
					if (cp[ale][ari])banlist[b[x]] |= 2;
					for (int y = x + 1; y <= r; y++) {
						if (loc[y] >= 0)continue;
						int ble = transb[b[y]][0];
						int bri = transb[b[y]][2];
						//left,left
						if (cp[ari][ble] && cp[bri][ale]) {
							nw.add_edge(b[x], b[y] + n);
							nw.add_edge(b[y], b[x] + n);
						}
						//left,right
						if (cp[ari][bri] && cp[ble][ale]) {
							nw.add_edge(b[x], b[y]);
							nw.add_edge(b[y] + n, b[x] + n);
						}
						//right,left
						if (cp[ale][ble] && cp[bri][ari]) {
							nw.add_edge(b[x] + n, b[y] + n);
							nw.add_edge(b[y], b[x]);
						}
						//right,right
						if (cp[ale][bri] && cp[ble][ari]) {
							nw.add_edge(b[x] + n, b[y]);
							nw.add_edge(b[y] + n, b[x]);
						}
					}
				}
				// cout << "?! " << l << " " << r << "\n";
				vector<bool> als(n);
				for (int x = l; x <= r; x++)if (loc[x] < 0)als[b[x]] = true;
				nw.scc();
				if (!nw.valid(n, banlist, als))continue;

				if (valid) {
					//cout << l << " " << r << " "<<i<<" "<<j<<"\n";
					ans = min(ans, l + (3 * n - 1 - r));
				}
			}
		}
	}
	if (ans == mod)ans = -1;
	//assert(ans >= 0);
	cout << ans << "\n";
}

signed main() {
	ios::sync_with_stdio(false);
	cin.tie(0);
	cout << fixed << setprecision(8);
	//init_f();
	//init();
	//expr();
	//int t; cin >> t; rep(i, t)
	solve();
	return 0;
}