#include <bits/stdc++.h>
using namespace std;
template <typename T>
void maxtt(T &t1, T t2) {
  t1 = max(t1, t2);
}
template <typename T>
void mintt(T &t1, T t2) {
  t1 = min(t1, t2);
}
bool debug = 0;
int n, m, k;
int dx[4] = {0, 1, 0, -1}, dy[4] = {1, 0, -1, 0};
string direc = "URDL";
long long ln, lk, lm;
void etp(bool f = 0) {
  puts(f ? "YES" : "NO");
  exit(0);
}
void addmod(int &x, int y, int mod = 1000000007) {
  assert(y >= 0);
  x += y;
  if (x >= mod) x -= mod;
  assert(x >= 0 && x < mod);
}
void et(int x = -1) {
  printf("%d\n", x);
  exit(0);
}
long long fastPow(long long x, long long y, int mod = 1000000007) {
  long long ans = 1;
  while (y > 0) {
    if (y & 1) ans = (x * ans) % mod;
    x = x * x % mod;
    y >>= 1;
  }
  return ans;
}
long long gcd1(long long x, long long y) { return y ? gcd1(y, x % y) : x; }
int f[1005][1005], N;
pair<int, int> pos[200135];
namespace LCT {
struct SplayNode {
} sn[200135];
const int N = 200135;
int ch[N][2];
int f[N], rev[N];
void PushUp(int p) {}
void PushDown(int p) {
  if (rev[p]) {
    swap(ch[p][0], ch[p][1]);
    rev[ch[p][0]] ^= 1;
    rev[ch[p][1]] ^= 1;
    rev[p] = 0;
  }
}
void Rotate(int x) {
  int y = f[x], z = f[y], k = (ch[f[x]][1] == x);
  if (!(ch[f[y]][0] != y && ch[f[y]][1] != y)) ch[z][ch[z][1] == y] = x;
  ch[y][k] = ch[x][!k];
  f[ch[y][k]] = y;
  ch[x][!k] = y;
  f[y] = x;
  f[x] = z;
  PushUp(y);
  PushUp(x);
}
inline void Update(int p) {
  if (!(ch[f[p]][0] != p && ch[f[p]][1] != p)) Update(f[p]);
  PushDown(p);
}
void Splay(int x) {
  Update(x);
  for (int fa; (fa = f[x]) != 0 && !(ch[f[x]][0] != x && ch[f[x]][1] != x);
       Rotate(x)) {
    if (!(ch[f[fa]][0] != fa && ch[f[fa]][1] != fa))
      Rotate((ch[f[fa]][1] == fa) == (ch[f[x]][1] == x) ? fa : x);
  }
  PushUp(x);
  PushDown(x);
}
int Access(int x) {
  int p;
  for (p = 0; x; p = x, x = f[x]) {
    Splay(x);
    ch[x][1] = p;
    PushUp(x);
  }
  return p;
}
void makeRoot(int p) {
  Access(p);
  Splay(p);
  rev[p] ^= 1;
}
void path(int p, int q) {
  makeRoot(p);
  Access(q);
  Splay(q);
}
int Find(int p) {
  Access(p);
  Splay(p);
  while (ch[p][0]) {
    PushDown(p);
    p = ch[p][0];
  }
  return p;
}
void link(int u, int v) {
  makeRoot(u);
  makeRoot(v);
  f[u] = v;
  PushUp(v);
}
void cut(int u, int v) {
  path(u, v);
  ch[v][0] = 0;
  f[u] = 0;
  PushUp(u);
  PushUp(v);
}
};  // namespace LCT
namespace ynk {
struct nd {
  int mi, cnt;
  nd() { mi = cnt = 0; }
  friend nd operator+(const nd &x, const nd &y) {
    nd res = nd();
    res.mi = min(x.mi, y.mi);
    if (res.mi == x.mi) res.cnt += x.cnt;
    if (res.mi == y.mi) res.cnt += y.cnt;
    return res;
  }
} T[200135 * 4];
int lz[200135 * 4];
void Up(int rt, int l, int r) { T[rt] = T[(rt << 1)] + T[(rt << 1 | 1)]; }
void Down(int rt, int l, int r) {
  if (lz[rt] != 0) {
    T[(rt << 1)].mi += lz[rt];
    lz[(rt << 1)] += lz[rt];
    T[(rt << 1 | 1)].mi += lz[rt];
    lz[(rt << 1 | 1)] += lz[rt];
    lz[rt] = 0;
  }
}
void build(int rt, int l, int r) {
  lz[rt] = 0;
  if (l + 1 == r) {
    T[rt].cnt = 1;
    return;
  }
  int mid = (l + r) / 2;
  build((rt << 1), l, mid);
  build((rt << 1 | 1), mid, r);
  Up(rt, l, r);
}
void upt(int rt, int l, int r, int L, int R, int val) {
  if (R <= l || r <= L) return;
  if (L <= l && r <= R) {
    T[rt].mi += val;
    lz[rt] += val;
    return;
  }
  Down(rt, l, r);
  int mid = (l + r) / 2;
  upt((rt << 1), l, mid, L, R, val);
  upt((rt << 1 | 1), mid, r, L, R, val);
  Up(rt, l, r);
}
nd qy(int rt, int l, int r, int L, int R) {
  if (L <= l && r <= R) {
    return T[rt];
  }
  Down(rt, l, r);
  int mid = (l + r) / 2;
  if (R <= mid)
    return qy((rt << 1), l, mid, L, R);
  else if (L >= mid)
    return qy((rt << 1 | 1), mid, r, L, R);
  else
    return qy((rt << 1), l, mid, L, mid) + qy((rt << 1 | 1), mid, r, mid, R);
}
};  // namespace ynk
void fmain(int tid) {
  scanf("%d%d", &n, &m);
  for (int(i) = 1; (i) <= (int)(n); (i)++) {
    for (int(j) = 1; (j) <= (int)(m); (j)++) {
      scanf("%d", &f[i][j]);
      pos[f[i][j]] = {i, j};
    }
  }
  N = n * m;
  int R = 0;
  ynk::build(1, 0, N);
  set<pair<int, int> > sp;
  long long ans = 0;
  for (int(i) = 1; (i) <= (int)(N); (i)++) {
    for (int(j) = 0; (j) < (int)(4); (j)++) {
      int x = pos[i].first + dx[j], y = pos[i].second + dy[j];
      if (f[x][y] == 0 || f[x][y] > i || f[x][y] <= R) continue;
      int tar = f[x][y];
      while (tar > R && LCT::Find(tar) == LCT::Find(i)) {
        R++;
        for (int(z) = 0; (z) < (int)(4); (z)++) {
          int X = pos[R].first + dx[z], Y = pos[R].second + dy[z];
          int u = min(R, f[X][Y]), v = max(R, f[X][Y]);
          if (sp.count({u, v})) {
            LCT::cut(u, v);
            sp.erase({u, v});
          }
        }
      }
      if (tar > R) {
        sp.insert({tar, i});
        LCT::link(tar, i);
      }
    }
    ynk::upt(1, 0, N, R, i, 1);
    for (int(j) = 0; (j) < (int)(4); (j)++) {
      int x = pos[i].first + dx[j], y = pos[i].second + dy[j];
      if (f[x][y] == 0 || f[x][y] > i || f[x][y] <= R) continue;
      int tar = f[x][y];
      ynk::upt(1, 0, N, R, tar, -1);
    }
    ynk::nd tmp = ynk::qy(1, 0, N, R, i);
    if (tmp.mi == 1) ans += tmp.cnt;
  }
  printf("%lld\n", ans);
}
int main() {
  int t = 1;
  for (int(i) = 1; (i) <= (int)(t); (i)++) {
    fmain(i);
  }
  return 0;
}
