#include <bits/stdc++.h>
using namespace std;
struct edge {
  long long to, cost;
};
const int inf = 1 << 27;
const long long INF = 1LL << 60;
const int COMBMAX = 1001001;
const long long MOD = 1000000007;
long long mpow(long long a, long long n, long long mod = MOD) {
  long long res = 1;
  while (n > 0) {
    if (n & 1) res = res * a % mod;
    a = a * a % mod;
    n >>= 1;
  }
  return res;
}
void yn(bool j) {
  cout << (j ? "Yes" : "No") << endl;
  return;
}
template <class Head>
void pt(Head&& head) {
  cout << head << endl;
  return;
}
template <class Head, class... Tail>
void pt(Head&& head, Tail&&... tail) {
  cout << head << " ";
  pt(forward<Tail>(tail)...);
}
template <class T>
void debug(T v) {
  for (int i = 0; i < (v.size()); ++i) cout << v[i] << " ";
  cout << endl;
}
template <class T>
void debug2(T v) {
  for (int i = 0; i < (v.size()); ++i) {
    for (int j = 0; j < (v[i].size()); ++j) cout << v[i][j] << " ";
    cout << endl;
  }
}
template <class T1, class T2>
long long bcount(T1 v, T2 a) {
  return (long long)distance((v).begin(),
                             upper_bound((v).begin(), (v).end(), a)) -
         (long long)distance((v).begin(),
                             lower_bound((v).begin(), (v).end(), a));
}
template <class T1, class T2>
inline bool chmin(T1& a, T2 b) {
  if (a > b) {
    a = b;
    return true;
  }
  return false;
}
template <class T1, class T2>
inline bool chmax(T1& a, T2 b) {
  if (a < b) {
    a = b;
    return true;
  }
  return false;
}
bool valid(long long n, long long h, long long w) {
  return (0 <= h && h < n && 0 <= w && w < n);
}
long long has(long long n, long long h, long long w) { return h * n + w; }
class UnionFind {
 public:
  vector<long long> par;
  vector<long long> siz;
  vector<long long> score;
  UnionFind(long long sz_)
      : par(sz_ * sz_), siz(sz_ * sz_, 1LL), score(sz_ * sz_) {
    for (long long i = 0; i < sz_ * sz_; ++i) par[i] = i;
    for (int i = 0; i < (sz_); ++i)
      for (int j = 0; j < (sz_); ++j) {
        score[has(sz_, i, j)] = i;
        chmin(score[has(sz_, i, j)], j);
        chmin(score[has(sz_, i, j)], sz_ - j - 1);
        chmin(score[has(sz_, i, j)], sz_ - i - 1);
      }
    sz_ *= sz_;
  }
  void init(long long sz_) {
    par.resize(sz_);
    siz.assign(sz_, 1LL);
    for (long long i = 0; i < sz_; ++i) par[i] = i;
  }
  long long find(long long x) {
    while (par[x] != x) {
      x = par[x] = par[par[x]];
    }
    return x;
  }
  bool merge(long long x, long long y) {
    x = find(x);
    y = find(y);
    if (x == y) return false;
    if (siz[x] < siz[y]) swap(x, y);
    siz[x] += siz[y];
    par[y] = x;
    chmin(score[x], score[y]);
    return true;
  }
  bool issame(long long x, long long y) { return find(x) == find(y); }
  long long size(long long x) { return siz[find(x)]; }
};
int main() {
  long long n;
  cin >> n;
  long long q = n * n;
  vector<long long> a(q);
  for (int i = 0; i < (q); ++i) cin >> a[i];
  UnionFind uf(n);
  long long ans = 0;
  for (int i = 0; i < (q); ++i) {
    a[i]--;
    ans += uf.score[a[i]];
    long long h = a[i] / n;
    long long w = a[i] % n;
    if (valid(n, h - 1, w)) uf.merge(has(n, h + 1, w), has(n, h, w));
    if (valid(n, h + 1, w)) uf.merge(has(n, h - 1, w), has(n, h, w));
    if (valid(n, h, w - 1)) uf.merge(has(n, h, w - 1), has(n, h, w));
    if (valid(n, h, w + 1)) uf.merge(has(n, h, w + 1), has(n, h, w));
  }
  pt(ans);
  return 0;
}
