#include <bits/stdc++.h>
const int N = 2000;
const int M = 2e5;
using namespace std;
int n, m, a[N + 1][N + 1], id[M + 1][2], dx[5] = {0, 1, -1, 0, 0},
                                         dy[5] = {0, 0, 0, 1, -1};
long long ans;
struct lct {
  int ch[M + 5][2], fa[M + 5], rv[M + 5], size[M + 5];
  bool chk(int x) { return ch[fa[x]][1] == x; }
  bool is(int x) { return ch[fa[x]][0] == x || ch[fa[x]][1] == x; }
  void pushup(int x) { size[x] = size[ch[x][0]] + size[ch[x][1]] + 1; }
  void rot(int x) {
    int y = fa[x], z = fa[y], k = chk(x);
    if (is(y)) ch[z][chk(y)] = x;
    fa[x] = z;
    ch[y][k] = ch[x][k ^ 1];
    fa[ch[x][k ^ 1]] = y;
    ch[x][k ^ 1] = y;
    fa[y] = x;
    pushup(y);
    pushup(x);
  }
  void rev(int x) {
    rv[x] ^= 1;
    swap(ch[x][0], ch[x][1]);
  }
  void pushdown(int x) {
    if (rv[x]) {
      rev(ch[x][0]);
      rev(ch[x][1]);
      rv[x] = 0;
    }
  }
  void pushall(int x) {
    if (is(x)) pushall(fa[x]);
    pushdown(x);
  }
  void splay(int x) {
    pushall(x);
    while (is(x)) {
      int y = fa[x];
      if (is(y)) {
        if (chk(x) == chk(y))
          rot(y);
        else
          rot(x);
      }
      rot(x);
    }
    pushup(x);
  }
  void access(int x) {
    for (int y = 0; x; y = x, x = fa[x]) splay(x), ch[x][1] = y, pushup(x);
  }
  void makert(int x) {
    access(x);
    splay(x);
    rev(x);
  }
  int findroot(int x) {
    access(x);
    splay(x);
    while (ch[x][0]) pushdown(x), x = ch[x][0];
    splay(x);
    return x;
  }
  void split(int x, int y) {
    makert(x);
    access(y);
    splay(y);
  }
  void link(int x, int y) {
    makert(x);
    fa[x] = y;
  }
  void cut(int x, int y) {
    split(x, y);
    fa[x] = ch[y][0] = 0;
    pushup(y);
  }
  void splay2(int x, int goal) {
    pushall(x);
    while (fa[x] != goal) {
      int y = fa[x];
      if (fa[y] != goal) {
        if (chk(x) == chk(y))
          rot(y);
        else
          rot(x);
      }
      rot(x);
    }
    pushup(x);
  }
  bool check(int x, int y) {
    if (findroot(x) != findroot(y)) return 0;
    makert(x);
    access(y);
    splay(x);
    splay2(y, x);
    return ch[y][0] == 0;
  }
  void del(int l, int r) {
    int x = id[l][0], y = id[l][1];
    for (int i = 1; i <= 4; i++) {
      int xx = x + dx[i], yy = y + dy[i];
      if (xx < 1 || xx > n || yy < 1 || yy > m) continue;
      int v = a[xx][yy];
      if (v >= l && v <= r && check(v, l)) cut(l, v);
    }
  }
} t;
struct Seg {
  int mi[M * 4 + 5], sm[M * 4 + 5], tag[M * 4 + 5];
  void pushup(int k) {
    sm[k] = 0;
    mi[k] = min(mi[k << 1], mi[k << 1 | 1]);
    if (mi[k] == mi[k << 1]) sm[k] += sm[k << 1];
    if (mi[k] == mi[k << 1 | 1]) sm[k] += sm[k << 1 | 1];
  }
  void build(int k, int l, int r) {
    if (l == r) {
      sm[k] = 1;
      return;
    }
    int mid = l + r >> 1;
    build(k << 1, l, mid);
    build(k << 1 | 1, mid + 1, r);
    pushup(k);
  }
  void add(int k, int l, int r, int z) {
    mi[k] += z;
    tag[k] += z;
  }
  void pushdown(int k, int l, int r, int mid) {
    if (tag[k]) {
      add(k << 1, l, mid, tag[k]);
      add(k << 1 | 1, mid + 1, r, tag[k]);
      tag[k] = 0;
    }
  }
  void modify(int k, int l, int r, int x, int y, int z) {
    if (l >= x && r <= y) {
      add(k, l, r, z);
      return;
    }
    int mid = l + r >> 1;
    pushdown(k, l, r, mid);
    if (x <= mid) modify(k << 1, l, mid, x, y, z);
    if (y > mid) modify(k << 1 | 1, mid + 1, r, x, y, z);
    pushup(k);
  }
  int query(int k, int l, int r, int x, int y) {
    if (l >= x && r <= y) {
      if (mi[k] == 1) return sm[k];
      return 0;
    }
    int mid = l + r >> 1;
    pushdown(k, l, r, mid);
    if (x > mid)
      return query(k << 1 | 1, mid + 1, r, x, y);
    else if (y <= mid)
      return query(k << 1, l, mid, x, y);
    else
      return query(k << 1, l, mid, x, y) + query(k << 1 | 1, mid + 1, r, x, y);
  }
} tree;
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]);
      id[a[i][j]][0] = i;
      id[a[i][j]][1] = j;
    }
  int nm = n * m, l = 1;
  tree.build(1, 1, nm);
  for (int r = 1; r <= nm; r++) {
    int x = id[r][0], y = id[r][1];
    for (int i = 1; i <= 4; i++) {
      int xx = x + dx[i], yy = y + dy[i];
      if (xx > n || xx < 1 || yy > m || yy < 1) continue;
      int v = a[xx][yy];
      while (v >= l && v <= r && t.findroot(v) == t.findroot(r)) t.del(l++, r);
      if (v >= l && v <= r) t.link(v, r);
    }
    tree.modify(1, 1, nm, l, r, 1);
    for (int i = 1; i <= 4; i++) {
      int xx = x + dx[i], yy = y + dy[i];
      if (xx > n || xx < 1 || yy > m || yy < 1) continue;
      int v = a[xx][yy];
      if (v >= l && v <= r) tree.modify(1, 1, nm, l, v, -1);
    }
    ans += tree.query(1, 1, nm, l, r);
  }
  cout << ans << endl;
  return 0;
}
