#include <bits/stdc++.h>
using namespace std;
int n, m, N, a[1005][1005];
pair<int, int> pos[200005];
namespace LCT {
int fa[200005], ch[200005][2];
bool rev[200005];
inline bool isc(int x) { return ch[fa[x]][1] == x; }
inline bool isr(int x) { return ch[fa[x]][0] != x && ch[fa[x]][1] != x; }
inline void rot(int x) {
  int y = fa[x], z = fa[y], c = isc(x);
  !isr(y) && (ch[z][isc(y)] = x);
  (ch[y][c] = ch[x][!c]) && (fa[ch[y][c]] = y);
  fa[ch[x][!c] = y] = x, fa[x] = z;
}
inline void pd(int x) {
  if (rev[x]) {
    swap(ch[x][0], ch[x][1]);
    rev[ch[x][0]] ^= 1, rev[ch[x][1]] ^= 1;
    rev[x] = 0;
  }
}
inline void pdpath(int x) {
  if (!isr(x)) pdpath(fa[x]);
  pd(x);
}
inline void splay(int x) {
  for (pdpath(x); !isr(x); rot(x))
    if (!isr(fa[x])) rot(isc(fa[x]) == isc(x) ? fa[x] : x);
}
inline void access(int x) {
  for (int y = 0; x; x = fa[y = x]) splay(x), ch[x][1] = y;
}
inline void bert(int x) { access(x), splay(x), rev[x] ^= 1; }
inline int sert(int x) {
  access(x), splay(x);
  for (; ch[x][0]; x = ch[x][0])
    ;
  return x;
}
inline void link(int x, int y) { bert(x), fa[x] = y; }
inline void cut(int x, int y) {
  bert(x), access(y), splay(y), ch[y][0] = fa[x] = 0;
}
inline bool connect(int x, int y) {
  bert(x);
  return sert(y) == x;
}
}  // namespace LCT
struct Segment_Tree {
  pair<int, int> val[200005 << 2];
  int tag[200005 << 2];
  void build(int i, int l, int r) {
    val[i] = pair<int, int>(0, r - l + 1);
    if (l == r) return;
    int mid = (l + r) >> 1;
    build(i << 1, l, mid), build(i << 1 | 1, mid + 1, r);
  }
  inline pair<int, int> merge(pair<int, int> a, pair<int, int> b) {
    if (a.first != b.first) return a.first < b.first ? a : b;
    return pair<int, int>(a.first, a.second + b.second);
  }
  inline void pushdown(int i) {
    if (tag[i])
      val[i << 1].first += tag[i], tag[i << 1] += tag[i],
          val[i << 1 | 1].first += tag[i], tag[i << 1 | 1] += tag[i],
          tag[i] = 0;
  }
  void modify(int i, int l, int r, int first, int second, int v) {
    if (first <= l && r <= second) {
      val[i].first += v, tag[i] += v;
      return;
    }
    int mid = (l + r) >> 1;
    pushdown(i);
    if (first <= mid) modify(i << 1, l, mid, first, second, v);
    if (second > mid) modify(i << 1 | 1, mid + 1, r, first, second, v);
    val[i] = merge(val[i << 1], val[i << 1 | 1]);
  }
  pair<int, int> query(int i, int l, int r, int first, int second) {
    if (first <= l && r <= second) return val[i];
    int mid = (l + r) >> 1;
    pair<int, int> ret = pair<int, int>(1e9, 0);
    pushdown(i);
    if (first <= mid) ret = merge(ret, query(i << 1, l, mid, first, second));
    if (second > mid)
      ret = merge(ret, query(i << 1 | 1, mid + 1, r, first, second));
    return ret;
  }
} T;
int dx[4] = {1, -1, 0, 0};
int dy[4] = {0, 0, 1, -1};
bool check(int k) {
  for (int i = 0, first; i < 4; i++)
    if (first = a[pos[k].first + dx[i]][pos[k].second + dy[i]])
      for (int j = i + 1, second; j < 4; j++)
        if (second = a[pos[k].first + dx[j]][pos[k].second + dy[j]])
          if (LCT::connect(first, second)) return 0;
  return 1;
}
void del(int k) {
  for (int i = 0, first; i < 4; i++)
    if (first = a[pos[k].first + dx[i]][pos[k].second + dy[i]])
      if (LCT::connect(k, first)) LCT::cut(k, first);
}
void solve(int l, int r) {
  for (int i = 0, first; i < 4; i++)
    if ((first = a[pos[r].first + dx[i]][pos[r].second + dy[i]]) >= l &&
        first <= r)
      LCT::link(first, r), T.modify(1, 1, N, l, first, -1);
  T.modify(1, 1, N, l, r, 1);
}
int main() {
  scanf("%d%d", &n, &m), N = n * m;
  for (int i = 1; i <= n; i++)
    for (int j = 1; j <= m; j++)
      scanf("%d", &a[i][j]), pos[a[i][j]] = pair<int, int>(i, j);
  T.build(1, 1, N);
  long long ans = 0;
  for (int l = 1, r = 1; r <= N; r++) {
    while (!check(r)) del(l++);
    solve(l, r);
    ans += T.query(1, 1, N, l, r).second;
  }
  printf("%I64d\n", ans);
}
