#include <bits/stdc++.h>
using namespace std;
using i64 = int64_t;
struct UnionFind {
  vector<int> p;
  UnionFind(int n) : p(vector<int>(n)) {
    for (int i = 0; i < n; ++i) p[i] = i;
  }
  int findset(int x) { return x == p[x] ? x : p[x] = findset(p[x]); }
  void merge(int x, int y) { p[findset(x)] = findset(y); }
};
int main() {
  std::ios_base::sync_with_stdio(false);
  int N;
  cin >> N;
  i64 ans = 0;
  vector<vector<int>> nextUp(N, vector<int>(N, -1));
  vector<vector<int>> nextDown(N, vector<int>(N, N));
  vector<int> f(N * N);
  UnionFind uf(N * N);
  for (int i = 0; i < N * N; ++i) {
    int v;
    cin >> v;
    v--;
    int y = v % N;
    int x = v / N;
    int bestCost = min(y + 1, N - y);
    for (int ny = 0; ny < N; ++ny) {
      for (int nx : {nextUp[x][ny], nextDown[x][ny]}) {
        int cost = abs(y - ny) + abs(x - nx);
        if (0 <= nx && nx < N) {
          cost += f[uf.findset(nx * N + ny)];
        }
        bestCost = min(bestCost, cost);
      }
    }
    f[v] = bestCost - 1;
    ans += bestCost - 1;
    static int dx[] = {1, 0, -1, 0};
    static int dy[] = {0, 1, 0, -1};
    for (int k = 0; k < 4; ++k) {
      int nx = x + dx[k], ny = y + dy[k];
      if (0 <= nx && nx < N && 0 <= ny && ny < N) {
        int w = nx * N + ny;
        if (nextUp[nx][ny] == nx) {
          int g1 = uf.findset(w);
          int g2 = uf.findset(v);
          int best = min(f[g1], f[g2]);
          uf.merge(g1, g2);
          f[uf.findset(g1)] = best;
        }
      }
    }
    for (int nx = 0; nx <= x; ++nx) {
      nextDown[nx][y] = min(nextDown[nx][y], x);
    }
    for (int nx = x; nx < N; ++nx) {
      nextUp[nx][y] = max(nextUp[nx][y], x);
    }
  }
  cout << ans << "\n";
  return 0;
}
