#include <bits/stdc++.h>
using namespace std;
const int MOD = 1000000007;
const int INF = 1000;
const int MAX_GRID_SIZE = 502 * 502;
const int EXIT = 0;
const int GONE = 1;
const int OCCUPIED = 2;
vector<int> occupied(MAX_GRID_SIZE);
vector<int> minHatedInf(MAX_GRID_SIZE);
vector<int> minHated(MAX_GRID_SIZE);
int N = 500;
inline int gridSideLength() { return N + 2; }
inline int gridSize() { return gridSideLength() * gridSideLength(); }
int xyToIndex(int x, int y) { return gridSideLength() * y + x - 1; }
int getAt(int x, int y, vector<int>& grid) { return grid[xyToIndex(x, y)]; }
void setAt(int x, int y, vector<int>& grid, int val) {
  grid[xyToIndex(x, y)] = val;
}
int dy[] = {-1, 0, 0, 1};
int dx[] = {0, -1, 1, 0};
int getMinHated(int x, int y) {
  int best = INF;
  queue<pair<int, int>> q;
  q.push({x, y});
  while (!q.empty()) {
    int currX = q.front().first;
    int currY = q.front().second;
    int currV = getAt(currX, currY, minHated);
    q.pop();
    if (best <= currV) continue;
    bool foundExit = false;
    for (int i = 0; i < (4); ++i) {
      int nextX = currX + dx[i];
      int nextY = currY + dy[i];
      if (getAt(nextX, nextY, occupied) == EXIT) {
        best = min(best, currV);
        foundExit = true;
        break;
      }
    }
    if (!foundExit) {
      for (int i = 0; i < (4); ++i) {
        int nextX = currX + dx[i];
        int nextY = currY + dy[i];
        if (getAt(nextX, nextY, occupied) == GONE) {
          if (currV < getAt(nextX, nextY, minHated)) {
            setAt(nextX, nextY, minHated, currV);
            q.push({nextX, nextY});
          }
        } else if (getAt(nextX, nextY, occupied) == OCCUPIED) {
          if (currV + 1 < getAt(nextX, nextY, minHated)) {
            setAt(nextX, nextY, minHated, currV + 1);
            q.push({nextX, nextY});
          }
        }
      }
    }
  }
  return best;
}
int main() {
  cin.tie(0);
  ios::sync_with_stdio(0);
  int N;
  cin >> N;
  for (int y = 1; y <= N; ++y) {
    for (int x = 1; x <= N; ++x) {
      setAt(x, y, minHatedInf, INF);
      setAt(x, y, occupied, OCCUPIED);
    }
  }
  int ans = 0;
  for (int i = 0; i < (N * N); ++i) {
    int P;
    cin >> P;
    int y = (P - 1) / N + 1;
    int x = (P - 1) % N + 1;
    memcpy(minHated.data(), minHatedInf.data(), sizeof(int) * gridSize());
    setAt(x, y, minHated, 0);
    ans += getMinHated(x, y);
    setAt(x, y, occupied, GONE);
  }
  cout << ans << endl;
  return 0;
}
