#include <bits/stdc++.h>
using namespace std;
char getc() {
  char c = getchar();
  while ((c < 'A' || c > 'Z') && (c < 'a' || c > 'z') && (c < '0' || c > '9'))
    c = getchar();
  return c;
}
int gcd(int n, int m) { return m == 0 ? n : gcd(m, n % m); }
int read() {
  int x = 0, f = 1;
  char c = getchar();
  while (c < '0' || c > '9') {
    if (c == '-') f = -1;
    c = getchar();
  }
  while (c >= '0' && c <= '9')
    x = (x << 1) + (x << 3) + (c ^ 48), c = getchar();
  return x * f;
}
int n, m, a[1010][1010], near[200010][4];
long long ans;
struct data {
  int ch[2], fa, rev;
} tree[200010];
void rev(int k) {
  if (k) swap(tree[k].ch[0], tree[k].ch[1]), tree[k].rev ^= 1;
}
void down(int k) {
  if (tree[k].rev) rev(tree[k].ch[0]), rev(tree[k].ch[1]), tree[k].rev = 0;
}
int whichson(int k) { return tree[tree[k].fa].ch[1] == k; }
bool isroot(int k) {
  return tree[tree[k].fa].ch[0] != k && tree[tree[k].fa].ch[1] != k;
}
void push(int k) {
  if (!isroot(k)) push(tree[k].fa);
  down(k);
}
void move(int k) {
  int fa = tree[k].fa, gf = tree[fa].fa, p = whichson(k);
  if (!isroot(fa)) tree[gf].ch[whichson(fa)] = k;
  tree[k].fa = gf;
  tree[fa].ch[p] = tree[k].ch[!p], tree[tree[k].ch[!p]].fa = fa;
  tree[k].ch[!p] = fa, tree[fa].fa = k;
}
void splay(int k) {
  push(k);
  while (!isroot(k)) {
    int fa = tree[k].fa;
    if (!isroot(fa))
      if (whichson(fa) ^ whichson(k))
        move(k);
      else
        move(fa);
    move(k);
  }
}
void access(int k) {
  for (int t = 0; k; t = k, k = tree[k].fa) splay(k), tree[k].ch[1] = t;
}
int findroot(int k) {
  if (!k) return 0;
  access(k);
  splay(k);
  for (; tree[k].ch[0]; k = tree[k].ch[0]) down(k);
  splay(k);
  return k;
}
void makeroot(int k) { access(k), splay(k), rev(k); }
void link(int x, int y) {
  makeroot(x);
  tree[x].fa = y;
}
void cut(int x, int y) {
  makeroot(x), access(y), splay(y);
  tree[y].ch[0] = tree[x].fa = 0;
}
int L[200010 << 2], R[200010 << 2], sum[200010 << 2], top[200010 << 2],
    lazy[200010 << 2];
void up(int k) {
  if (top[k << 1] == top[k << 1 | 1]) {
    top[k] = top[k << 1];
    sum[k] = sum[k << 1] + sum[k << 1 | 1];
  } else if (top[k << 1] < top[k << 1 | 1])
    top[k] = top[k << 1], sum[k] = sum[k << 1];
  else
    top[k] = top[k << 1 | 1], sum[k] = sum[k << 1 | 1];
}
void build(int k, int l, int r) {
  L[k] = l, R[k] = r;
  if (l == r) {
    sum[k] = 1;
    return;
  }
  int mid = l + r >> 1;
  build(k << 1, l, mid);
  build(k << 1 | 1, mid + 1, r);
  up(k);
}
void Down(int k) {
  top[k << 1] += lazy[k], top[k << 1 | 1] += lazy[k];
  lazy[k << 1] += lazy[k], lazy[k << 1 | 1] += lazy[k];
  lazy[k] = 0;
}
void add(int k, int l, int r, int op) {
  if (L[k] == l && R[k] == r) {
    lazy[k] += op;
    top[k] += op;
    return;
  }
  if (lazy[k]) Down(k);
  int mid = L[k] + R[k] >> 1;
  if (r <= mid)
    add(k << 1, l, r, op);
  else if (l > mid)
    add(k << 1 | 1, l, r, op);
  else
    add(k << 1, l, mid, op), add(k << 1 | 1, mid + 1, r, op);
  up(k);
}
int query(int k, int l, int r) {
  if (L[k] == l && R[k] == r) return (top[k] == 1) * sum[k];
  if (lazy[k]) Down(k);
  int mid = L[k] + R[k] >> 1;
  if (r <= mid)
    return query(k << 1, l, r);
  else if (l > mid)
    return query(k << 1 | 1, l, r);
  else
    return query(k << 1, l, mid) + query(k << 1 | 1, mid + 1, r);
}
void print(int k, int l, int r) {
  if (L[k] == R[k]) {
    cout << top[k] << ' ';
    return;
  }
  if (lazy[k]) Down(k);
  int mid = L[k] + R[k] >> 1;
  if (r <= mid)
    print(k << 1, l, r);
  else if (l > mid)
    print(k << 1 | 1, l, r);
  else
    print(k << 1, l, mid), print(k << 1 | 1, mid + 1, r);
}
signed main() {
  n = read(), m = read();
  for (int i = 1; i <= n; i++)
    for (int j = 1; j <= m; j++) a[i][j] = read();
  for (int i = 1; i <= n; i++)
    for (int j = 1; j <= m; j++) {
      near[a[i][j]][0] = a[i - 1][j];
      near[a[i][j]][1] = a[i + 1][j];
      near[a[i][j]][2] = a[i][j - 1];
      near[a[i][j]][3] = a[i][j + 1];
    }
  build(1, 1, n * m);
  int l = 1;
  for (int i = 1; i <= n * m; i++) {
    bool flag;
    do {
      flag = 0;
      int u[5], t = 0;
      u[t++] = findroot(i);
      for (int j = 0; j < 4; j++)
        if (near[i][j]) u[t++] = findroot(near[i][j]);
      for (int x = 0; x < t; x++)
        for (int y = x + 1; y < t; y++)
          if (u[x] == u[y]) {
            flag = 1;
            break;
          }
      if (!flag) break;
      for (int j = 0; j < 4; j++)
        if (near[l][j] >= l && near[l][j] < i) cut(l, near[l][j]);
      l++;
    } while (1);
    add(1, l, i, 1);
    for (int j = 0; j < 4; j++)
      if (near[i][j] >= l && near[i][j] <= i)
        link(i, near[i][j]), add(1, l, near[i][j], -1);
    ans += query(1, l, i);
  }
  cout << ans;
  return 0;
}
