#include <bits/stdc++.h>
using namespace std;
const long long MOD = 1e9 + 7;
int dx[4] = {1, 0, -1, 0};
int dy[4] = {0, 1, 0, -1};
struct UnionFind {
 private:
  vector<int> par;
  vector<int> siz;

 public:
  void init(int N) {
    par.resize(N);
    siz.resize(N);
    for (int i = 0; i < N; i++) par[i] = i;
    for (int i = 0; i < N; i++) siz[i] = 1;
  }
  void unite(int a, int b) {
    int rootA = root(a);
    int rootB = root(b);
    if (rootA == rootB) return;
    if (siz[rootA] < siz[rootB]) swap(rootA, rootB);
    par[rootB] = rootA;
    siz[rootA] += siz[rootB];
  }
  int root(int a) {
    if (par[a] == a) return a;
    return par[a] = root(par[a]);
  }
  bool same(int a, int b) { return root(a) == root(b); }
  int size(int a) { return siz[root(a)]; }
};
int N;
int P[500 * 500];
int nxt[500 * 500];
UnionFind uf;
bool stand[500 * 500] = {};
bool goal[500 * 500] = {};
int ans = 0;
int solve(int n) {
  n = uf.root(n);
  int ret = 0;
  while (!goal[n]) {
    if (!stand[nxt[n]]) ret++;
    n = uf.root(nxt[n]);
  }
  return ret;
}
signed main() {
  cin >> N;
  for (int(i) = 0; (i) < (N * N); (i)++) {
    cin >> P[i];
    P[i]--;
  }
  for (int(i) = 0; (i) < (N * N); (i)++) {
    int y = i / N;
    int x = i % N;
    int m = min({y, N - 1 - y, x, N - 1 - x});
    if (y == m) nxt[i] = i - N;
    if (N - 1 - y == m) nxt[i] = i + N;
    if (x == m) nxt[i] = i - 1;
    if (N - 1 - x == m) nxt[i] = i + 1;
    if (nxt[i] < 0 || nxt[i] >= N * N) nxt[i] = 0;
    if (m == 0) goal[i] = true;
  }
  uf.init(N * N);
  for (int(i) = 0; (i) < (N * N); (i)++) {
    int y = P[i] / N;
    int x = P[i] % N;
    stand[P[i]] = true;
    ans += solve(P[i]);
    for (int(j) = 0; (j) < (4); (j)++) {
      if (0 <= y + dy[j] && y + dy[j] < N && 0 <= x + dx[j] && x + dx[j] < N) {
        if (stand[(y + dy[j]) * N + x + dx[j]]) {
          if (uf.same(nxt[uf.root(P[i])], (y + dy[j]) * N + x + dx[j])) {
            int tmp = nxt[uf.root((y + dy[j]) * N + x + dx[j])];
            bool g = goal[uf.root((y + dy[j]) * N + x + dx[j])] ||
                     goal[uf.root(P[i])];
            uf.unite((y + dy[j]) * N + x + dx[j], P[i]);
            nxt[uf.root(P[i])] = tmp;
            goal[uf.root(P[i])] |= g;
          } else if (uf.same(nxt[(y + dy[j]) * N + x + dx[j]], uf.root(P[i]))) {
            int tmp = nxt[uf.root(P[i])];
            bool g = goal[uf.root((y + dy[j]) * N + x + dx[j])] ||
                     goal[uf.root(P[i])];
            uf.unite((y + dy[j]) * N + x + dx[j], P[i]);
            nxt[uf.root(P[i])] = tmp;
            goal[uf.root(P[i])] |= g;
          } else if (solve((y + dy[j]) * N + x + dx[j]) <= solve(P[i])) {
            int tmp = nxt[uf.root((y + dy[j]) * N + x + dx[j])];
            bool g = goal[uf.root((y + dy[j]) * N + x + dx[j])] ||
                     goal[uf.root(P[i])];
            uf.unite((y + dy[j]) * N + x + dx[j], P[i]);
            nxt[uf.root(P[i])] = tmp;
            goal[uf.root(P[i])] |= g;
          } else {
            int tmp = nxt[uf.root(P[i])];
            bool g = goal[uf.root((y + dy[j]) * N + x + dx[j])] ||
                     goal[uf.root(P[i])];
            uf.unite((y + dy[j]) * N + x + dx[j], P[i]);
            nxt[uf.root(P[i])] = tmp;
            goal[uf.root(P[i])] |= g;
          }
        }
      }
    }
    for (int(j) = 0; (j) < (4); (j)++) {
      if (0 <= y + dy[j] && y + dy[j] < N && 0 <= x + dx[j] && x + dx[j] < N) {
        if (!stand[(y + dy[j]) * N + x + dx[j]]) {
          if (nxt[uf.root(P[i])] == (y + dy[j]) * N + x + dx[j]) continue;
          if (solve(P[i]) > solve((y + dy[j]) * N + x + dx[j])) continue;
          nxt[(y + dy[j]) * N + x + dx[j]] = P[i];
        }
      }
    }
  }
  cout << ans << endl;
}
