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.
1
2
3
2
 8
190409007 190409007 352375776 190409007 352375776 352375776 352375776 352375776
190409007 190409007 190409007 190409007 190409007 352375776 352375776 190409007
190409007 352375776 352375776 190409007 190409007 190409007 352375776 352375776
 1
1
1
1
 1
377489979
588153796
588153796
 2
1 1
2 2
3 3
 4
1 1 1 1
1 1 1 1
1 1 1 1
 2
1 2
2 2
1 1
 3
1 1 2
1 1 3
1 1 4

2
 2
 1
 2
 3
 1
 2
 9

#include <bits/stdc++.h>
using namespace std;
const long long MAXN = 1000000;
const long long INF = 2000000000;
struct Item {
  Item *l, *r;
  long long Value;
  long long Ind[3];
  long long Maximum;
  long long revInd[3];
  Item(long long v = 0, long long m0 = INF, long long m1 = INF,
       long long m2 = INF) {
    Value = v;
    Ind[0] = m0;
    Ind[1] = m1;
    Ind[2] = m2;
    l = NULL;
    r = NULL;
    Maximum = 0;
  }
};
long long N, M;
long long value[3][MAXN];
map<long long, Item> itemFromValue;
vector<Item *> itemPointer, coordSort[3];
long long optimalAns = INF;
struct CheatArray {
  long long A[MAXN];
  long long Link[MAXN];
  CheatArray() {}
  long long operator[](long long i) { return A[Link[i]]; }
  long long ValidQ(long long i) { return i >= 0 && i < N && Link[i] != -1; }
  void Erase(long long i) { i == 0 ? Link[i] = -1 : Link[i] = Link[i - 1]; }
};
struct SegmentTree {
  long long tree[MAXN];
  void build(long long l = 0, long long r = M, long long v = 0) {
    if (r - l == 1) {
      tree[v] = coordSort[1][l]->Ind[2];
      return;
    }
    long long m = (l + r) / 2;
    build(l, m, 2 * v + 1);
    build(m, r, 2 * v + 2);
    tree[v] = max(tree[2 * v + 1], tree[2 * v + 2]);
  }
  long long getMax(long long tl, long long tr, long long l = 0, long long r = M,
                   long long v = 0) {
    if (l >= r || tl >= tr) return INF;
    if (l == tl && r == tr) return tree[v];
    long long m = (l + r) / 2;
    if (tr <= m) return getMax(tl, tr, l, m, 2 * v + 1);
    if (m <= tl) return getMax(tl, tr, m, r, 2 * v + 2);
    return max(getMax(tl, m, l, m, 2 * v + 1), getMax(m, tr, m, r, 2 * v + 2));
  }
  void modify(long long pos, long long val, long long l = 0, long long r = M,
              long long v = 0) {
    if (r - l == 1 && l == pos) {
      tree[v] = val;
      return;
    }
    long long m = (l + r) / 2;
    if (pos < m) modify(pos, val, l, m, 2 * v + 1);
    if (pos >= m) modify(pos, val, m, r, 2 * v + 2);
    tree[v] = max(tree[2 * v + 1], tree[2 * v + 2]);
  }
};
CheatArray arrayOfSecondIndex;
SegmentTree arrayOfThirdIndex;
void Input() {
  scanf("%I64d", &N);
  for (long long k = 0; k < 3; k++)
    for (long long i = 0; i < N; i++) scanf("%I64d", &value[k][i]);
}
void BuildItemFromValueMap() {
  for (long long k = 0; k < 3; k++)
    for (long long i = N - 1; i >= 0; i--)
      itemFromValue[value[k][i]].Ind[k] = i,
      itemFromValue[value[k][i]].Value = value[k][i];
}
void FormItemPointer() {
  for (map<long long, Item>::iterator it = itemFromValue.begin();
       it != itemFromValue.end(); it++)
    itemPointer.push_back(&(it->second));
  M = itemPointer.size();
  for (long long k = 0; k < 3; k++) {
    auto SortForCoordComporator = [k](Item *a, Item *b) -> bool {
      return a->Ind[k] < b->Ind[k];
    };
    coordSort[k] = itemPointer;
    sort(coordSort[k].begin(), coordSort[k].end(), SortForCoordComporator);
    for (long long i = 0; i < M; i++) coordSort[k][i]->revInd[k] = i;
  }
}
void BuildCheatArray() {
  for (long long i = 0; i < M; i++) {
    arrayOfSecondIndex.A[i] = coordSort[1][i]->Ind[1];
    arrayOfSecondIndex.Link[i] = i;
  }
}
void BuildSegmentTree() { arrayOfThirdIndex.build(); }
long long Func(long long secondArrayIndex, long long add) {
  long long q;
  if (secondArrayIndex == -1)
    q = (arrayOfThirdIndex.getMax(0, M) + 1) + add;
  else
    q = (arrayOfSecondIndex[secondArrayIndex] + 1) +
        (arrayOfThirdIndex.getMax(secondArrayIndex + 1, M) + 1) + add;
  optimalAns = min(optimalAns, q);
  return q;
}
void TernarySearch(long long add) {
  long long L = 0;
  for (; L < M && !arrayOfSecondIndex.ValidQ(L); L++)
    ;
  long long R = M;
  Func(-1, add);
  while (R - L > 50) {
    long long M1 = L + (R - L) / 3;
    long long M2 = R - (R - L) / 3;
    if (Func(M2, add) < Func(M1, add))
      L = M1;
    else
      R = M2;
  }
  for (long long q = L; q < R; q++) Func(q, add);
}
void Erase(long long i) {
  arrayOfSecondIndex.Erase(coordSort[0][i]->revInd[1]);
  arrayOfThirdIndex.modify(coordSort[0][i]->revInd[1], -1);
}
void Solve() {
  TernarySearch(0);
  for (long long i = 0; i < M; i++) {
    long long add = coordSort[0][i]->Ind[0] + 1;
    Erase(i);
    TernarySearch(add);
  }
}
int main() {
  Input();
  BuildItemFromValueMap();
  FormItemPointer();
  BuildCheatArray();
  BuildSegmentTree();
  Solve();
  cout << optimalAns << endl;
  return 0;
}
