#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 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;
  vector<vector<E>> edges;
  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),
        edges(V),
        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);
      edges[e.u].push_back(e);
      edges[e.v].push_back(e);
    }
    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};
  }
};
struct index_t {
  int i;
  explicit operator int() { return i; }
  friend bool operator<(const index_t& a, const index_t& b) {
    return a.i < b.i;
  }
  friend bool operator<=(const index_t& a, const index_t& b) {
    return a.i <= b.i;
  }
  friend bool operator>(const index_t& a, const index_t& b) {
    return a.i > b.i;
  }
  index_t operator+(int b) { return {i + b}; }
  index_t operator-(int b) { return {i - b}; }
  int operator-(index_t b) { return i - b.i; }
  friend ostream& operator<<(ostream& o, index_t a) {
    o << a.i;
    return o;
  }
};
using range_t = pair<index_t, index_t>;
using ranges = vector<range_t>;
template <typename E>
struct heavy_path_decomposition {
  const tree<E>& t;
  struct heavy_path {
    index_t index;
    int htop;
  };
  vector<heavy_path> hld;
  heavy_path_decomposition() {}
  heavy_path_decomposition(const tree<E>& _t) : t(_t), hld(t.V) {
    for (int i = 0; i < t.V; i++) {
      int u = t.preorder[i];
      hld[u] = {index_t{i}, i > 0 && t.preorder[i - 1] == t.par[u]
                                ? hld[t.par[u]].htop
                                : u};
    }
  }
  index_t index(int v) const { return hld[v].index; }
  int at_index(index_t i) const { return t.preorder[int(i)]; }
  int htop(int v) const { return hld[v].htop; }
  range_t subtree(int v) const { return {index(v), index(v) + t.subt_sz[v]}; }
  int lca(int u, int v) const {
    while (htop(u) != htop(v)) {
      int& jump = index(htop(u)) > index(htop(v)) ? u : v;
      jump = t.par[htop(jump)];
    }
    return t.depth[u] < t.depth[v] ? u : v;
  }
  int dist(int u, int v) const {
    return t.depth[u] + t.depth[v] - 2 * t.depth[lca(u, v)];
  }
  bool uv_path_has_w(int u, int v, int w) const {
    return w != -1 && dist(u, v) == (dist(u, w) + dist(w, v));
  }
  bool is_ancestor(int anc, int desc) const {
    return index(anc) <= index(desc) &&
           index(desc) < index(anc) + t.subt_sz[anc];
  }
  int first_step(int u, int v) const {
    assert(u != v);
    if (!is_ancestor(u, v)) return t.par[u];
    return *upper_bound(
        (t.children[u]).begin(), (t.children[u]).end(), v,
        [&](int v, int c) { return index(v) < index(c) + t.subt_sz[c]; });
  }
  mutable int path_lca;
  mutable ranges path_up, path_down;
  void decompose_path(int u, int v, bool include_lca) const {
    path_up.clear(), path_down.clear();
    while (htop(u) != htop(v)) {
      int& jump = index(htop(u)) > index(htop(v)) ? u : v;
      (jump == u ? path_up : path_down)
          .emplace_back(index(htop(jump)), index(jump) + 1);
      jump = t.par[htop(jump)];
    }
    path_lca = t.depth[u] < t.depth[v] ? u : v;
    if (u != v || include_lca) {
      (u != path_lca ? path_up : path_down)
          .emplace_back(index(path_lca) + !include_lca,
                        index(path_lca ^ u ^ v) + 1);
    }
    reverse((path_down).begin(), (path_down).end());
  }
  template <typename FOR, typename FORd>
  void for_each(int u, int v, bool include_lca, const FOR& first,
                const FORd& fd) const {
    decompose_path(u, v, include_lca);
    for (range_t r : path_up) first(r.first, r.second);
    for (range_t r : path_down) fd(r.first, r.second);
  }
  template <typename FOR>
  void for_each_commutative(int u, int v, bool include_lca,
                            const FOR& first) const {
    for_each(u, v, include_lca, first, first);
  }
  template <typename T, typename OP, typename FOLDL, typename FOLDR>
  T accumulate(int u, int v, bool include_lca, T iv, const OP& lplus,
               const FOLDL& fl, const FOLDR& fr) const {
    decompose_path(u, v, include_lca);
    for (range_t r : path_up) iv = lplus(iv, fr(r.first, r.second));
    for (range_t r : path_down) iv = lplus(iv, fl(r.first, r.second));
    return iv;
  }
  template <typename T, typename OP, typename FOLD>
  T accumulate_commutative(int u, int v, bool include_lca, T iv,
                           const OP& lplus, const FOLD& first) const {
    return accumulate(u, v, include_lca, iv, lplus, first, first);
  }
};
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);
  heavy_path_decomposition<E> hld(tr);
  int diam = 0;
  int deepest = 0;
  auto intro = [&](int u) {
    if (tr.depth[u] > tr.depth[deepest]) {
      diam++;
      deepest = u;
    } else {
      ckmax(diam, hld.dist(deepest, u));
    }
  };
  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(diam);
  }
  return 0;
}
