Problem: There are three arrays a, b and c. Each of them consists of n integers. SmallY wants to find three integers u, v, w (0 ≤ u, v, w ≤ n) such that the following condition holds: each number that appears in the union of a, b and c, appears either in the first u elements of a, or in the first v elements of b, or in the first w elements of c. Of course, SmallY doesn't want to have huge numbers u, v and w, so she wants sum u + v + w to be as small as possible.

Please, help her to find the minimal possible sum of u + v + w.

Input

The first line contains a single integer n (1 ≤ n ≤ 105). The second line contains n space-separated integers a1, a2, ..., an — array a. The third line contains the description of array b in the same format. The fourth line contains the description of array c in the same format. The following constraint holds: 1 ≤ ai, bi, ci ≤ 109.

Output

Print a single integer — the minimum possible sum of u + v + w.

Examples

Input

3
1 1 101
1 2 1
3 2 1


Output

5

Input

5
1 1 2 2 3
2 2 4 3 3
3 3 1 1 1


Output

5

Note

In the first example you should choose u = 3, v = 0, w = 2. 

In the second example you should choose u = 1, v = 3, w = 1.

Solution (in CPP):

Solution:
#include <bits/stdc++.h>
using namespace std;
template <class T, class T2>
inline void chkmax(T &x, const T2 &y) {
  if (x < y) x = y;
}
template <class T, class T2>
inline void chkmin(T &x, const T2 &y) {
  if (x > y) x = y;
}
const int MAXN = (1 << 20);
const int inf = (int)1e9 + 17;
struct node {
  int lazy, mx, ans;
  node() {
    ans = inf;
    mx = 0;
    lazy = 0;
  }
  node(int val, int _ans) {
    mx = val;
    ans = _ans;
    lazy = 0;
  }
};
node temp, broken;
node merge(node l, node r) {
  temp.mx = max(l.mx, r.mx);
  temp.ans = min(l.ans, r.ans);
  temp.lazy = 0;
  return temp;
}
struct segment_tree {
  node tr[4 * MAXN];
  void push(int l, int r, int idx) {
    if (tr[idx].lazy) {
      tr[idx].mx = max(tr[idx].mx, tr[idx].lazy);
      tr[idx].ans = tr[idx].mx + l;
      if (l != r) {
        chkmax(tr[2 * idx + 1].lazy, tr[idx].lazy);
        chkmax(tr[2 * idx + 2].lazy, tr[idx].lazy);
      }
      tr[idx].lazy = 0;
    }
  }
  void init(int l, int r, int idx) {
    if (l == r) {
      tr[idx] = node(0, l);
      return;
    }
    int mid = (l + r) >> 1;
    init(l, mid, 2 * idx + 1);
    init(mid + 1, r, 2 * idx + 2);
    tr[idx] = merge(tr[2 * idx + 1], tr[2 * idx + 2]);
  }
  void update(int qL, int qR, int val, int l, int r, int idx) {
    push(l, r, idx);
    if (qL > r || l > qR) return;
    if (qL <= l && r <= qR) {
      tr[idx].lazy = val;
      push(l, r, idx);
      return;
    }
    int mid = (l + r) >> 1;
    update(qL, qR, val, l, mid, 2 * idx + 1);
    update(qL, qR, val, mid + 1, r, 2 * idx + 2);
    tr[idx] = merge(tr[2 * idx + 1], tr[2 * idx + 2]);
  }
  node query(int qL, int qR, int l, int r, int idx) {
    push(l, r, idx);
    if (l > qR || r < qL) return broken;
    if (qL <= l && r <= qR) return tr[idx];
    int mid = (l + r) >> 1;
    return merge(query(qL, qR, l, mid, 2 * idx + 1),
                 query(qL, qR, mid + 1, r, 2 * idx + 2));
  }
};
int n;
int a[MAXN];
int b[MAXN];
int c[MAXN];
void read() {
  cin >> n;
  for (int i = 0; i < n; i++) cin >> a[i];
  for (int j = 0; j < n; j++) cin >> b[j];
  for (int k = 0; k < n; k++) cin >> c[k];
}
segment_tree t;
int fa[MAXN], fb[MAXN], fc[MAXN];
int cnt[MAXN];
void add(int x) {
  if (fc[x] == 0) {
    t.update(0, fb[x] - 1, inf, 0, n, 0);
    return;
  }
  int low = 0, high = -1 + ((fb[x] == 0) ? n + 1 : fb[x]), mid, ret = -1;
  while (low <= high) {
    mid = (low + high) >> 1;
    if (t.query(mid, mid, 0, n, 0).mx < fc[x])
      ret = mid, high = mid - 1;
    else
      low = mid + 1;
  }
  if (ret == -1) return;
  int up = -1 + ((fb[x] == 0) ? n + 1 : fb[x]);
  if (ret <= up) t.update(ret, up, fc[x], 0, n, 0);
}
int query() { return t.query(0, n, 0, n, 0).ans; }
void solve() {
  vector<int> li_all;
  for (int i = 0; i < n; i++) li_all.push_back(a[i]);
  for (int i = 0; i < n; i++) li_all.push_back(b[i]);
  for (int i = 0; i < n; i++) li_all.push_back(c[i]);
  sort(li_all.begin(), li_all.end());
  li_all.erase(unique(li_all.begin(), li_all.end()), li_all.end());
  for (int i = 0; i < n; i++)
    a[i] = lower_bound(li_all.begin(), li_all.end(), a[i]) - li_all.begin();
  for (int i = 0; i < n; i++)
    b[i] = lower_bound(li_all.begin(), li_all.end(), b[i]) - li_all.begin();
  for (int i = 0; i < n; i++)
    c[i] = lower_bound(li_all.begin(), li_all.end(), c[i]) - li_all.begin();
  for (int i = n - 1; i >= 0; i--) a[i + 1] = a[i];
  for (int i = n - 1; i >= 0; i--) b[i + 1] = b[i];
  for (int i = n - 1; i >= 0; i--) c[i + 1] = c[i];
  for (int i = n; i >= 1; i--) fa[a[i]] = i, fb[b[i]] = i, fc[c[i]] = i;
  for (int i = 1; i <= n; i++) cnt[a[i]]++;
  t.init(0, n, 0);
  for (int l = 0; l < (int)li_all.size(); l++)
    if (cnt[l] == 0) add(l);
  int answer = query() + n;
  for (int i = n; i >= 1; i--) {
    cnt[a[i]]--;
    if (cnt[a[i]] == 0 && fb[a[i]] == 0 && fc[a[i]] == 0) break;
    if (cnt[a[i]] == 0) add(a[i]);
    chkmin(answer, i + query() - 1);
  }
  cout << answer << '\n';
}
int main() {
  ios_base::sync_with_stdio(false);
  cin.tie(NULL);
  read();
  solve();
  return 0;
}