#include <bits/stdc++.h>
using namespace std;
using ll = long long;
using vi = vector<int>;
using vvi = vector<vi>;
using vll = vector<ll>;
using vvll = vector<vll>;
using vb = vector<bool>;
using vd = vector<double>;
using vs = vector<string>;
using pii = pair<int, int>;
using pll = pair<ll, ll>;
using pdd = pair<double, double>;
using vpii = vector<pii>;
using vvpii = vector<vpii>;
using vpll = vector<pll>;
using vvpll = vector<vpll>;
using vpdd = vector<pdd>;
using vvpdd = vector<vpdd>;
template <typename T>
void ckmin(T& a, const T& b) {
  a = min(a, b);
}
template <typename T>
void ckmax(T& a, const T& b) {
  a = max(a, b);
}
mt19937_64 rng(chrono::steady_clock::now().time_since_epoch().count());
namespace __input {
template <class T1, class T2>
void re(pair<T1, T2>& p);
template <class T>
void re(vector<T>& a);
template <class T, size_t SZ>
void re(array<T, SZ>& a);
template <class T>
void re(T& x) {
  cin >> x;
}
void re(double& x) {
  string t;
  re(t);
  x = stod(t);
}
template <class Arg, class... Args>
void re(Arg& first, Args&... rest) {
  re(first);
  re(rest...);
}
template <class T1, class T2>
void re(pair<T1, T2>& p) {
  re(p.first, p.second);
}
template <class T>
void re(vector<T>& a) {
  for (int i = 0; i < (int((a).size())); i++) re(a[i]);
}
template <class T, size_t SZ>
void re(array<T, SZ>& a) {
  for (int i = 0; i < (SZ); i++) re(a[i]);
}
}  // namespace __input
using namespace __input;
namespace __output {
template <class T1, class T2>
void pr(const pair<T1, T2>& x);
template <class T, size_t SZ>
void pr(const array<T, SZ>& x);
template <class T>
void pr(const vector<T>& x);
template <class T>
void pr(const deque<T>& x);
template <class T>
void pr(const set<T>& x);
template <class T1, class T2>
void pr(const map<T1, T2>& x);
template <class T>
void pr(const T& x) {
  cout << x;
}
template <class Arg, class... Args>
void pr(const Arg& first, const Args&... rest) {
  pr(first);
  pr(rest...);
}
template <class T1, class T2>
void pr(const pair<T1, T2>& x) {
  pr("{", x.first, ", ", x.second, "}");
}
template <class T, bool pretty = true>
void prContain(const T& x) {
  if (pretty) pr("{");
  bool fst = 1;
  for (const auto& a : x) pr(!fst ? pretty ? ", " : " " : "", a), fst = 0;
  if (pretty) pr("}");
}
template <class T>
void pc(const T& x) {
  prContain<T, false>(x);
  pr("\n");
}
template <class T, size_t SZ>
void pr(const array<T, SZ>& x) {
  prContain(x);
}
template <class T>
void pr(const vector<T>& x) {
  prContain(x);
}
template <class T>
void pr(const deque<T>& x) {
  prContain(x);
}
template <class T>
void pr(const set<T>& x) {
  prContain(x);
}
template <class T1, class T2>
void pr(const map<T1, T2>& x) {
  prContain(x);
}
void ps() { pr("\n"); }
template <class Arg>
void ps(const Arg& first) {
  pr(first);
  ps();
}
template <class Arg, class... Args>
void ps(const Arg& first, const Args&... rest) {
  pr(first, " ");
  ps(rest...);
}
}  // namespace __output
using namespace __output;
namespace __algorithm {
template <typename T>
void dedup(vector<T>& v) {
  sort((v).begin(), (v).end());
  v.erase(unique((v).begin(), (v).end()), v.end());
}
template <typename T>
typename vector<T>::iterator find(vector<T>& v, const T& x) {
  auto it = lower_bound((v).begin(), (v).end(), x);
  return it != v.end() && *it == x ? it : v.end();
}
template <typename T>
size_t index(vector<T>& v, const T& x) {
  auto it = find(v, x);
  assert(it != v.end() && *it == x);
  return it - v.begin();
}
template <typename C, typename T, typename OP>
vector<T> prefixes(const C& v, T id, OP op) {
  vector<T> r(int((v).size()) + 1, id);
  for (int i = 0; i < (int((v).size())); i++) r[i + 1] = op(r[i], v[i]);
  return r;
}
template <typename C, typename T, typename OP>
vector<T> suffixes(const C& v, T id, OP op) {
  vector<T> r(int((v).size()) + 1, id);
  for (int i = (int((v).size())) - 1; i >= 0; i--) r[i] = op(v[i], r[i + 1]);
  return r;
}
}  // namespace __algorithm
using namespace __algorithm;
struct monostate {
  friend istream& operator>>(istream& is,
                             const __attribute__((unused)) monostate& ms) {
    return is;
  }
  friend ostream& operator<<(ostream& os,
                             const __attribute__((unused)) monostate& ms) {
    return os;
  }
} ms;
namespace __io {
void setIn(string second) { freopen(second.c_str(), "r", stdin); }
void setOut(string second) { freopen(second.c_str(), "w", stdout); }
void setIO(string second = "") {
  ios_base::sync_with_stdio(0);
  cin.tie(0);
  cout << fixed << setprecision(15);
  if (int((second).size())) {
    setIn(second + ".in"), setOut(second + ".out");
  }
}
}  // namespace __io
using namespace __io;
template <typename T, typename F>
struct segment_tree {
  int SZ;
  T id;
  F tt;
  vector<T> table;
  segment_tree() {}
  segment_tree(int _SZ, T _id, F _tt) : SZ(_SZ), id(_id), tt(_tt) {
    table.resize(2 * SZ, id);
  }
  template <typename L>
  void set_leaves(L create) {
    for (int i = 0; i < SZ; i++) table[SZ + i] = create(i);
    for (int i = SZ - 1; i; i--) table[i] = tt(table[2 * i], table[2 * i + 1]);
  }
  void replace(int i, T v) {
    table[i += SZ] = v;
    for (i /= 2; i > 0; i /= 2) {
      table[i] = tt(table[2 * i], table[2 * i + 1]);
    }
  }
  T operator()(int i, int j) const {
    T left = id, right = id;
    for (i += SZ, j += SZ; i < j; i /= 2, j /= 2) {
      if (i & 1) left = tt(left, table[i++]);
      if (j & 1) right = tt(table[--j], right);
    }
    return tt(left, right);
  }
  const T& operator[](int i) const { return table[SZ + i]; }
};
template <typename W = monostate>
struct wedge {
  int u, v, i;
  W w;
  wedge<W>(int _u = -1, int _v = -1, int _i = -1, W _w = W{})
      : u(_u), v(_v), i(_i), w(_w) {}
  int operator[](int loc) const { return u ^ v ^ loc; }
  friend void pr(const wedge& e) { pr(e.u, "<-", e.w, "->", e.v); }
  template <bool FIRST_INDEX = 1>
  friend void re(wedge& e) {
    re(e.u, e.v, e.w);
    if (FIRST_INDEX) --e.u, --e.v;
  }
  template <bool FIRST_INDEX = 1>
  friend void re(wedge& e, int _u) {
    e.u = _u;
    re(e.v, e.w);
    if (FIRST_INDEX) --e.v;
  }
};
enum INPUT_FORMAT { EDGE_LIST, PARENT_LIST };
template <typename E>
struct tree {
  vector<E> edge_list;
  int V, root;
  vvi nbrs, children;
  vi par, depth, subt_sz;
  vi preorder, reverse_preorder;
  vb erased;
  void erase(int u) { erased[u] = true; }
  tree(int _V = 0) : V(_V) {}
  tree(const vector<E>& __edge_list, int _root = 0)
      : edge_list(__edge_list),
        V(int((__edge_list).size()) + 1),
        root(_root),
        nbrs(V),
        children(V),
        par(V, -1),
        depth(V),
        subt_sz(V),
        erased(V) {
    for (E& e : edge_list) {
      assert(0 <= e.u && e.u < V && 0 <= e.v && e.v < V);
      nbrs[e.u].push_back(e.v);
      nbrs[e.v].push_back(e.u);
    }
    init(root);
    build_preorder(root);
    reverse_preorder = preorder;
    reverse((reverse_preorder).begin(), (reverse_preorder).end());
  }
  void init(int u) {
    subt_sz[u] = 1;
    for (int v : nbrs[u])
      if (v != par[u]) {
        par[v] = u;
        depth[v] = depth[u] + 1;
        init(v);
        subt_sz[u] += subt_sz[v];
        children[u].push_back(v);
        if (subt_sz[v] > subt_sz[children[u].front()])
          swap(children[u].front(), children[u].back());
      }
  }
  void build_preorder(int u) {
    preorder.push_back(u);
    for (int v : children[u]) build_preorder(v);
  }
  template <INPUT_FORMAT FMT = EDGE_LIST, bool FIRST_INDEX = 1>
  friend void re(tree& t) {
    assert(t.V > 0);
    vector<E> __edge_list(t.V - 1);
    for (int i = 0; i < t.V - 1; i++) {
      E& e = __edge_list[i];
      if (FMT == EDGE_LIST)
        re<FIRST_INDEX>(e);
      else
        re<FIRST_INDEX>(e, i + 1);
      e.i = i;
    }
    t = tree<E>(__edge_list);
  }
  friend void pr(const tree& t) { pr("{V=", t.V, " ", t.edge_list, "}"); }
  mutable vi __subt_sz;
  void __calc_subt_sz(int u, bool avoid_erased, int p) const {
    __subt_sz[u] = 1;
    for (int v : nbrs[u])
      if (v != p && (!avoid_erased || !erased[v])) {
        __calc_subt_sz(v, avoid_erased, u);
        __subt_sz[u] += __subt_sz[v];
      }
  }
  vi centroids(int r = 0, bool avoid_erased = 1) const {
    if (__subt_sz.empty()) __subt_sz.resize(V);
    __calc_subt_sz(r, avoid_erased, -1);
    int c = r, p = -1;
  FIND:
    for (int u : nbrs[c])
      if (!avoid_erased || !erased[u]) {
        if (subt_sz[u] < subt_sz[c] && 2 * subt_sz[u] >= subt_sz[r]) {
          p = c, c = u;
          goto FIND;
        }
      }
    return subt_sz[c] * 2 == subt_sz[r] ? vi{c, p} : vi{c};
  }
};
template <typename E, int L>
struct centroid_decomposition {
  const tree<E>& t;
  vi layer;
  vpii par;
  vi layer_order;
  vector<array<int, L>> anc_dist;
  centroid_decomposition(const tree<E>& _t)
      : t(_t), layer(t.V, -1), par(t.V), anc_dist(t.V), subt_sz(t.V) {
    assert((1 << L) >= t.V);
    calc_subt_sz();
    decompose();
  }
  vi subt_sz;
  void calc_subt_sz(int u = 0, int p = -1) {
    subt_sz[u] = 1;
    for (int v : t.nbrs[u])
      if (v != p) {
        calc_subt_sz(v, u);
        subt_sz[u] += subt_sz[v];
      }
  }
  pii centroids(int r) {
    int c = r, p = -1;
  FIND:
    for (int u : t.nbrs[c])
      if (layer[u] == -1) {
        if (subt_sz[u] < subt_sz[c] && 2 * subt_sz[u] >= subt_sz[r]) {
          p = c, c = u;
          goto FIND;
        }
      }
    return subt_sz[c] * 2 == subt_sz[r] ? pii{c, p} : pii{c, -1};
  }
  void calc_preorder(int u, int p, int r, int rly) {
    subt_sz[u] = 1;
    anc_dist[u][rly] = u == r ? 0 : 1 + anc_dist[p][rly];
    for (int v : t.nbrs[u])
      if (v != p && layer[v] == -1) {
        calc_preorder(v, u, r, rly);
        subt_sz[u] += subt_sz[v];
      }
  }
  int decompose(int r = 0, int p = -1, int pi = 0, int ly = 1) {
    par[r = centroids(r).first] = {p, pi};
    layer[r] = ly, layer_order.push_back(r);
    calc_preorder(r, -1, r, ly - 1);
    int cn = 0;
    for (int u : t.nbrs[r])
      if (layer[u] == -1) {
        decompose(u, r, cn++, ly + 1);
      }
    return r;
  }
};
int main() {
  setIO();
  int V = 4;
  using E = wedge<>;
  vector<E> elist;
  for (int u = 0; u < (3); u++) elist.push_back({0, 1 + u});
  int Q;
  re(Q);
  vi ops(Q);
  re(ops);
  for (int q = 0; q < (Q); q++) {
    --ops[q];
    elist.push_back({ops[q], V++});
    elist.push_back({ops[q], V++});
  }
  tree<E> tr(elist);
  centroid_decomposition<E, 21> cd(tr);
  const int INF = -1e9;
  vector<pair<pii, pii>> far(V, {{INF, INF}, {INF, INF}});
  auto comb = [](pair<pii, pii>& r, pii pos) {
    if (pos.first > r.first.first) {
      if (r.first.second != pos.second) r.second = r.first;
      r.first = pos;
    } else if (pos.first > r.second.first && pos.second != r.first.second) {
      r.second = pos;
    }
  };
  int D = 0;
  auto intro = [&](int u) {
    int p = u, pi = -1;
    assert(cd.layer[u] < 25);
    for (int i = (cd.layer[u]) - 1; i >= 0; i--) {
      int d = cd.anc_dist[u][i];
      ckmax(D, d + (far[p].first.second == pi ? far[p].second.first
                                              : far[p].first.first));
      comb(far[p], {d, pi});
      tie(p, pi) = cd.par[p];
    }
  };
  for (int u = 0; u < (4); u++) intro(u);
  for (int q = 0; q < (Q); q++) {
    intro(4 + 2 * q);
    intro(4 + 2 * q + 1);
    ps(D);
  }
  return 0;
}
