#include <bits/stdc++.h>
using namespace std;
namespace Tzh {
const int maxn = 200010, maxm = 1010;
const int mx[] = {-1, 1, 0, 0}, my[] = {0, 0, -1, 1};
int id[maxm][maxm], n, m, early[maxn], h;
long long ans;
pair<int, int> pos[maxn];
namespace LCT {
struct Tr {
  int ch[2], rev, fa;
} tree[maxn << 1];
bool root(int now) {
  return tree[tree[now].fa].ch[1] != now && tree[tree[now].fa].ch[0] != now;
}
void rotate(int now) {
  int fa = tree[now].fa, ffa = tree[fa].fa, son = tree[fa].ch[1] == now;
  if (!root(fa)) tree[ffa].ch[tree[ffa].ch[1] == fa] = now;
  if (tree[now].ch[son ^ 1]) tree[tree[now].ch[son ^ 1]].fa = fa;
  tree[fa].ch[son] = tree[now].ch[son ^ 1];
  tree[fa].fa = now;
  tree[now].fa = ffa;
  tree[now].ch[son ^ 1] = fa;
}
void change(int now) {
  tree[now].rev ^= 1;
  swap(tree[now].ch[0], tree[now].ch[1]);
}
void pushdown(int now) {
  if (tree[now].rev) {
    change(tree[now].ch[0]);
    change(tree[now].ch[1]);
    tree[now].rev ^= 1;
  }
}
void push(int now) {
  if (!root(now)) push(tree[now].fa);
  pushdown(now);
}
void splay(int now) {
  push(now);
  while (!root(now)) {
    int fa = tree[now].fa;
    if (root(fa))
      rotate(now);
    else if ((tree[tree[fa].fa].ch[1] == fa) ^ (tree[fa].ch[1] == now))
      rotate(now), rotate(now);
    else
      rotate(fa), rotate(now);
  }
}
void access(int fa) {
  for (int now = 0; fa; now = fa, fa = tree[fa].fa)
    splay(fa), tree[fa].ch[1] = now;
}
void makeroot(int now) {
  access(now);
  splay(now);
  change(now);
}
int findroot(int now) {
  access(now);
  splay(now);
  pushdown(now);
  while (tree[now].ch[0]) push(tree[now].ch[0]), now = tree[now].ch[0];
  splay(now);
  return now;
}
void split(int x, int y) {
  makeroot(y);
  access(x);
  splay(x);
}
void link(int x, int y) {
  makeroot(x);
  if (findroot(y) == x) return;
  tree[x].fa = y;
}
void cut(int x, int y) {
  makeroot(x);
  if (findroot(y) == x && tree[y].fa == x && !tree[y].ch[1])
    tree[y].fa = tree[x].ch[0] = 0;
}
bool connect(int x, int y) {
  makeroot(y);
  return findroot(x) == y;
}
}  // namespace LCT
struct Tr {
  int tag, val, num;
} tree[maxn << 2];
bool check(int x, int y) {
  for (int i = 0; i < 4; i++) {
    int xx = x + mx[i], yy = y + my[i];
    if (xx <= n && xx > 0 && yy <= m && yy > 0) {
      if (id[x][y] < id[xx][yy] || id[xx][yy] < h) continue;
      if (LCT::connect(id[x][y], id[xx][yy])) {
        for (int i = 0; i < 4; i++) {
          int xx = x + mx[i], yy = y + my[i];
          if (xx <= n && xx > 0 && yy <= m && yy > 0)
            LCT::cut(id[x][y], id[xx][yy]);
        }
        return 0;
      }
      LCT::link(id[x][y], id[xx][yy]);
    }
  }
  return 1;
}
void del(int now) {
  int x = pos[now].first, y = pos[now].second;
  for (int i = 0; i < 4; i++) {
    int xx = x + mx[i], yy = y + my[i];
    if (xx <= n && xx > 0 && yy <= m && yy > 0) LCT::cut(id[x][y], id[xx][yy]);
  }
}
void update(int now) {
  tree[now].val = min(tree[now << 1 | 1].val, tree[now << 1].val);
  tree[now].num = 0;
  if (tree[now << 1].val == tree[now].val) tree[now].num += tree[now << 1].num;
  if (tree[now << 1 | 1].val == tree[now].val)
    tree[now].num += tree[now << 1 | 1].num;
}
void change(int now, int val) {
  tree[now].tag += val;
  tree[now].val += val;
}
void pushdown(int now) {
  if (tree[now].tag != 0) {
    change(now << 1, tree[now].tag);
    change(now << 1 | 1, tree[now].tag);
    tree[now].tag = 0;
  }
}
void add(int now, int lt, int rt, int l, int r, int val) {
  if (l > rt || r < lt) return;
  int mid = lt + rt >> 1;
  if (l <= lt && r >= rt) return change(now, val);
  pushdown(now);
  add(now << 1, lt, mid, l, r, val);
  add(now << 1 | 1, mid + 1, rt, l, r, val);
  update(now);
}
int ask(int now, int lt, int rt, int l, int r) {
  if (l > rt || r < lt) return 0;
  int mid = lt + rt >> 1;
  if (l <= lt && r >= rt) return tree[now].val == 1 ? tree[now].num : 0;
  pushdown(now);
  return ask(now << 1, lt, mid, l, r) + ask(now << 1 | 1, mid + 1, rt, l, r);
}
void build(int now, int lt, int rt) {
  tree[now].num = rt - lt + 1;
  if (lt == rt) return;
  int mid = lt + rt >> 1;
  build(now << 1, lt, mid);
  build(now << 1 | 1, mid + 1, rt);
}
void work() {
  scanf("%d%d", &n, &m);
  h = 1;
  for (int i = 1; i <= n; i++)
    for (int j = 1; j <= m; j++)
      scanf("%d", &id[i][j]), pos[id[i][j]] = pair<int, int>(i, j);
  for (int i = 1; i <= n * m; i++) {
    int x = pos[i].first, y = pos[i].second;
    while (!check(x, y)) del(h++);
    early[i] = h;
    for (int i = 0; i < 4; i++) {
      int xx = x + mx[i], yy = y + my[i];
      if (xx <= n && xx > 0 && yy <= m && yy > 0 && id[xx][yy] <= id[x][y] &&
          id[xx][yy] >= h)
        LCT::link(id[x][y], id[xx][yy]);
    }
  }
  build(1, 1, n * m);
  for (int i = 1; i <= n * m; i++) {
    int x = pos[i].first, y = pos[i].second;
    add(1, 1, n * m, 1, i, 1);
    for (int j = 0; j < 4; j++) {
      int xx = x + mx[j], yy = y + my[j];
      if (xx <= n && xx > 0 && yy <= m && yy > 0)
        if (id[xx][yy] <= i) add(1, 1, n * m, 1, id[xx][yy], -1);
    }
    ans += ask(1, 1, n * m, early[i], i);
  }
  printf("%lld", ans);
  return;
}
}  // namespace Tzh
int main() {
  Tzh::work();
  return 0;
}
