#include <bits/stdc++.h>
using namespace std;
const int N = 200010;
const int px[] = {0, 0, 1, -1}, py[] = {1, -1, 0, 0};
int n, m, a[1010][1010], tx[N], ty[N], f[N], ch[N][2], rev[N], tr[N * 4],
    cnt[N * 4], tag[N * 4];
long long ans;
bool isroot(int x) {
  return !x || !f[x] || (ch[f[x]][0] != x && ch[f[x]][1] != x);
}
int which(int x) { return ch[f[x]][1] == x; }
void rotate(int x) {
  int fx = f[x], ffx = f[fx], d = which(x);
  if (!isroot(fx)) ch[ffx][which(fx)] = x;
  f[x] = f[fx];
  ch[fx][d] = ch[x][d ^ 1];
  f[ch[x][d ^ 1]] = fx;
  ch[x][d ^ 1] = fx;
  f[fx] = x;
  return;
}
void rever(int x) {
  rev[x] ^= 1;
  swap(ch[x][0], ch[x][1]);
  return;
}
void pushdown(int x) {
  if (rev[x]) {
    if (ch[x][0]) rever(ch[x][0]);
    if (ch[x][1]) rever(ch[x][1]);
    rev[x] = 0;
  }
  return;
}
void push(int x) {
  if (!isroot(x)) push(f[x]);
  pushdown(x);
  return;
}
void splay(int x) {
  push(x);
  while (!isroot(x)) {
    int fx = f[x];
    if (!isroot(fx)) {
      if (which(x) == which(fx))
        rotate(fx);
      else
        rotate(x);
    }
    rotate(x);
  }
  return;
}
void access(int x) {
  for (int y = 0; x; y = x, x = f[x]) {
    splay(x);
    ch[x][1] = y;
  }
  return;
}
void makeroot(int x) {
  access(x);
  splay(x);
  rever(x);
  return;
}
void link(int x, int y) {
  makeroot(x);
  f[x] = y;
  return;
}
int getroot(int x) {
  access(x);
  splay(x);
  while (ch[x][0]) x = ch[x][0];
  return x;
}
void cut(int x, int y) {
  makeroot(x);
  access(y);
  splay(y);
  if (!ch[x][1] && ch[y][0] == x) f[x] = ch[y][0] = 0;
  return;
}
bool check(int x, int y) {
  makeroot(x);
  access(y);
  splay(y);
  while (f[x]) x = f[x];
  return x == y;
}
void sgtpushdown(int o) {
  if (tag[o]) {
    tr[o << 1] += tag[o];
    tr[o << 1 | 1] += tag[o];
    tag[o << 1] += tag[o];
    tag[o << 1 | 1] += tag[o];
    tag[o] = 0;
  }
  return;
}
void pushup(int o) {
  if (tr[o << 1] == tr[o << 1 | 1]) {
    tr[o] = tr[o << 1];
    cnt[o] = cnt[o << 1] + cnt[o << 1 | 1];
  } else if (tr[o << 1] < tr[o << 1 | 1]) {
    tr[o] = tr[o << 1];
    cnt[o] = cnt[o << 1];
  } else {
    tr[o] = tr[o << 1 | 1];
    cnt[o] = cnt[o << 1 | 1];
  }
  return;
}
void build(int o, int l, int r) {
  tr[o] = 0;
  cnt[o] = r - l + 1;
  if (l == r) return;
  int mid = (l + r) >> 1;
  build(o << 1, l, mid);
  build(o << 1 | 1, mid + 1, r);
  return;
}
void update(int o, int l, int r, int L, int R, int v) {
  if (L <= l && r <= R) {
    tag[o] += v;
    tr[o] += v;
    return;
  }
  sgtpushdown(o);
  int mid = (l + r) >> 1;
  if (L <= mid) update(o << 1, l, mid, L, R, v);
  if (R > mid) update(o << 1 | 1, mid + 1, r, L, R, v);
  pushup(o);
  return;
}
int query(int o, int l, int r, int L, int R) {
  if (tr[o] > 1) return 0;
  if (L <= l && r <= R) return tr[o] * cnt[o];
  sgtpushdown(o);
  int mid = (l + r) >> 1, ret = 0;
  if (L <= mid) ret += query(o << 1, l, mid, L, R);
  if (R > mid) ret += query(o << 1 | 1, mid + 1, r, L, R);
  return ret;
}
int main() {
  scanf("%d%d", &n, &m);
  for (int i = 1; i <= n; i++)
    for (int j = 1; j <= m; j++) {
      scanf("%d", a[i] + j);
      tx[a[i][j]] = i;
      ty[a[i][j]] = j;
    }
  int M = n * m;
  build(1, 1, M);
  for (int l = n * m, r = l; l >= 1; l--) {
    int x = tx[l], y = ty[l];
    for (int i = 0; i <= 3; i++) {
      int nx = x + px[i], ny = y + py[i];
      if (nx <= n && nx >= 1 && ny <= m && ny >= 1) {
        while (a[nx][ny] >= l && a[nx][ny] <= r && check(a[x][y], a[nx][ny])) {
          for (int j = 0; j <= 3; j++) {
            int mx = tx[r] + px[j], my = ty[r] + py[j];
            if (mx <= n && mx >= 1 && my <= m && my >= 1)
              cut(a[tx[r]][ty[r]], a[mx][my]);
          }
          r--;
        }
        if (a[nx][ny] >= l && a[nx][ny] <= r) {
          link(a[x][y], a[nx][ny]);
          update(1, 1, M, a[nx][ny], r, -1);
        }
      }
    }
    update(1, 1, M, l, r, 1);
    ans += query(1, 1, M, l, r);
  }
  printf("%lld\n", ans);
  return 0;
}
