#include <bits/stdc++.h>
using namespace std;
using lli = long long int;
void YESNO(bool), YesNo(bool);
template <class T1, class T2>
bool chmin(T1 &l, const T2 &r);
template <class T1, class T2>
bool chmax(T1 &l, const T2 &r);
template <class T1, class T2>
void vadd(vector<T1> &v, T2 x);
struct ufind {
  struct node {
    long long int par, rank, size;
    void init(long long int i) {
      par = i;
      rank = 0;
      size = 1;
    }
  };
  vector<node> nodes;
  ufind(long long int n) {
    nodes.resize(n);
    for (lli i = 0; i < (n); i++) nodes[i].init(i);
  }
  long long int find(long long int x) {
    return nodes[x].par == x ? x : (nodes[x].par = find(nodes[x].par));
  }
  void unite(long long int x, long long int y) {
    x = find(x);
    y = find(y);
    if (x == y) return;
    if (nodes[x].rank < nodes[y].rank) {
      nodes[x].par = y;
      nodes[y].size += nodes[x].size;
    } else {
      nodes[y].par = x;
      if (nodes[x].rank == nodes[y].rank) nodes[x].rank++;
      nodes[x].size += nodes[y].size;
    }
  }
  bool same(long long int x, long long int y) { return find(x) == find(y); }
  long long int size(long long int x) { return nodes[find(x)].size; }
};
long long int f[505 * 505] = {};
set<long long int> adj[505 * 505];
long long int N;
void dump_grid() { return; }
signed main() {
  cin >> N;
  auto get = [=](long long int x, long long int y) {
    if (x < 0 || x >= N || y >= N || y < 0) return N * N;
    return x * N + y;
  };
  ufind uf(N * N + 1);
  vector<long long int> P(N * N + 1);
  vector<long long int> used(N * N + 1);
  for (lli i = 0; i < (N); i++)
    for (lli j = 0; j < (N); j++) {
      f[get(i, j)] = min({i, j, N - i - 1, N - j - 1});
    }
  long long int ret = 0;
  used[N * N] = true;
  long long int dx[4] = {-1, 0, 1, 0};
  long long int dy[4] = {0, 1, 0, -1};
  map<long long int, long long int> hoge;
  for (lli i = 0; i < (N * N); i++) {
    cin >> P[i];
    P[i]--;
  }
  for (lli i = 0; i < (N * N); i++) {
    long long int X = i / N;
    long long int Y = i % N;
    for (lli j = 0; j < (4); j++) {
      long long int nx1 = dx[j] + X;
      long long int ny1 = dy[j] + Y;
      adj[i].insert(get(nx1, ny1));
    }
  }
  long long int out = N * N;
  for (lli i = 0; i < (N * N); i++) {
    long long int X = P[i] / N;
    long long int Y = P[i] % N;
    long long int score = f[uf.find(get(X, Y))];
    deque<pair<long long int, long long int>> que;
    map<long long int, bool> visited;
    que.push_front({uf.find(get(X, Y)), 0});
    while (!que.empty()) {
      auto [cur, dep] = que.front();
      que.pop_front();
      if (visited[cur]) continue;
      if (uf.same(cur, out)) {
        ret += dep;
        break;
      }
      visited[cur] = true;
      for (auto s : adj[cur]) {
        long long int t = uf.find(s);
        if (visited[t]) continue;
        if (used[t]) {
          que.push_front({t, dep});
        } else {
          que.push_back({t, dep + 1});
        }
      }
    }
    for (lli j = 0; j < (4); j++) {
      long long int id = uf.find(get(X, Y));
      long long int nx1 = dx[j] + X;
      long long int ny1 = dy[j] + Y;
      long long int id1 = uf.find(get(nx1, ny1));
      long long int score1 = f[id1];
      if (used[id1]) {
        if (adj[id].size() > adj[id1].size()) {
          for (auto s : adj[id1]) adj[id].insert(s);
        } else {
          for (auto s : adj[id]) adj[id1].insert(s);
          swap(adj[id], adj[id1]);
        }
        uf.unite(id, id1);
        if (id != uf.find(id)) {
          swap(adj[id], adj[id1]);
        }
      }
    }
    used[uf.find(P[i])] = true;
    dump_grid();
  }
  cout << ret << endl;
}
void YESNO(bool b) { cout << (b ? "YES" : "NO") << endl; }
void YesNo(bool b) { cout << (b ? "Yes" : "No") << endl; }
template <class T1, class T2>
bool chmin(T1 &l, const T2 &r) {
  return (l > r) ? (l = r, true) : false;
}
template <class T1, class T2>
bool chmax(T1 &l, const T2 &r) {
  return (l < r) ? (l = r, true) : false;
}
template <class T1, class T2>
void vadd(vector<T1> &v, T2 x) {
  for (auto &s : v) s += T2(x);
}
