```go
package main
import (
"bufio"
"fmt"
"os"
)
var scanner *bufio.Scanner
func nextInt() int {
scanner.Scan()
res := 0
for _, b := range scanner.Bytes() {
res = res*10 + int(b-'0')
}
return res
}
type Node struct {
ch [2]int
fa int
rev bool
val int
min_node int
}
var tr []Node
var eu []int
var ev []int
func isRoot(x int) bool {
return tr[tr[x].fa].ch[0] != x && tr[tr[x].fa].ch[1] != x
}
func pushup(x int) {
tr[x].min_node = x
if l := tr[x].ch[0]; l != 0 {
if tr[tr[l].min_node].val < tr[tr[x].min_node].val {
tr[x].min_node = tr[l].min_node
}
}
if r := tr[x].ch[1]; r != 0 {
if tr[tr[r].min_node].val < tr[tr[x].min_node].val {
tr[x].min_node = tr[r].min_node
}
}
}
func pushdown(x int) {
if tr[x].rev {
l := tr[x].ch[0]
r := tr[x].ch[1]
if l != 0 {
tr[l].rev = !tr[l].rev
}
if r != 0 {
tr[r].rev = !tr[r].rev
}
tr[x].ch[0] = r
tr[x].ch[1] = l
tr[x].rev = false
}
}
func rotate(x int) {
y := tr[x].fa
z := tr[y].fa
k := 0
if tr[y].ch[1] == x {
k = 1
}
if !isRoot(y) {
if tr[z].ch[1] == y {
tr[z].ch[1] = x
} else {
tr[z].ch[0] = x
}
}
tr[x].fa = z
tr[y].ch[k] = tr[x].ch[k^1]
if tr[x].ch[k^1] != 0 {
tr[tr[x].ch[k^1]].fa = y
}
tr[x].ch[k^1] = y
tr[y].fa = x
pushup(y)
pushup(x)
}
func pushdownAll(x int) {
if !isRoot(x) {
pushdownAll(tr[x].fa)
}
pushdown(x)
}
func splay(x int) {
pushdownAll(x)
for !isRoot(x) {
y := tr[x].fa
z := tr[y].fa
if !isRoot(y) {
yK := (tr[y].ch[1] == x)
zK := (tr[z].ch[1] == y)
if yK == zK {
rotate(y)
} else {
rotate(x)
}
}
rotate(x)
}
}
func access(x int) {
for y := 0; x != 0; y, x = x, tr[x].fa {
splay(x)
tr[x].ch[1] = y
pushup(x)
}
}
func makeroot(x int) {
access(x)
splay(x)
tr[x].rev = !tr[x].rev
}
func findroot(x int) int {
access(x)
splay(x)
for tr[x].ch[0] != 0 {
pushdown(x)
x = tr[x].ch[0]
}
splay(x)
return x
}
func link(x, y int) {
makeroot(x)
tr[x].fa = y
}
func cut(x, y int) {
makeroot(x)
access(y)
splay(y)
tr[y].ch[0] = 0
tr[x].fa = 0
pushup(y)
}
type SegNode struct {
min_val int
count int
lazy int
}
var seg []SegNode
func build(u, l, r int) {
seg[u].min_val = 0
seg[u].count = r - l + 1
seg[u].lazy = 0
if l == r {
return
}
mid := (l + r) / 2
build(u*2, l, mid)
build(u*2+1, mid+1, r)
}
func apply(u, v int) {
seg[u].min_val += v
seg[u].lazy += v
}
func pushupSeg(u int) {
if seg[u*2].min_val < seg[u*2+1].min_val {
seg[u].min_val = seg[u*2].min_val
seg[u].count = seg[u*2].count
} else if seg[u*2].min_val > seg[u*2+1].min_val {
seg[u].min_val = seg[u*2+1].min_val
seg[u].count = seg[u*2+1].count
} else {
seg[u].min_val = seg[u*2].min_val
seg[u].count = seg[u*2].count + seg[u*2+1].count
}
}
func pushdownSeg(u int) {
if seg[u].lazy != 0 {
apply(u*2, seg[u].lazy)
apply(u*2+1, seg[u].lazy)
seg[u].lazy = 0
}
}
func update(u, l, r, ql, qr, v int) {
if ql <= l && r <= qr {
apply(u, v)
return
}
pushdownSeg(u)
mid := (l + r) / 2
if ql <= mid {
update(u*2, l, mid, ql, qr, v)
}
if qr > mid {
update(u*2+1, mid+1, r, ql, qr, v)
}
pushupSeg(u)
}
func query(u, l, r, ql, qr int) (int, int) {
if ql <= l && r <= qr {
return seg[u].min_val, seg[u].count
}
pushdownSeg(u)
mid := (l + r) / 2
min_val := int(1e9)
count := 0
if ql <= mid {
min_val, count = query(u*2, l, mid, ql, qr)
}
if qr > mid {
v, c := query(u*2+1, mid+1, r, ql, qr)
if v < min_val {
min_val = v
count = c
} else if v == min_val {
count += c
}
}
return min_val, count
}
func main() {
scanner = bufio.NewScanner(os.Stdin)
scanner.Split(bufio.ScanWords)
scanner.Buffer(make([]byte, 1024*1024), 10*1024*1024)
n := nextInt()
m := nextInt()
V := n * m
posR := make([]int, V+1)
posC := make([]int, V+1)
grid := make([][]int, n+1)
for i := 1; i <= n; i++ {
grid[i] = make([]int, m+1)
for j := 1; j <= m; j++ {
val := nextInt()
grid[i][j] = val
posR[val] = i
posC[val] = j
}
}
tr = make([]Node, 4*V+1)
eu = make([]int, 4*V+1)
ev = make([]int, 4*V+1)
seg = make([]SegNode, 4*V+1)
for i := 1; i <= V; i++ {
tr[i].val = 1e9
tr[i].min_node = i
}
edge_idx := V
build(1, 1, V)
var ans int64
L_cycle := 0
dirs := [][]int{{-1, 0}, {1, 0}, {0, -1}, {0, 1}}
for r := 1; r <= V; r++ {
i, j := posR[r], posC[r]
update(1, 1, V, 1, r, 1)
for _, dir := range dirs {
ni, nj := i+dir[0], j+dir[1]
if ni >= 1 && ni <= n && nj >= 1 && nj <= m {
v := grid[ni][nj]
if v < r {
update(1, 1, V, 1, v, -1)
if findroot(v) == findroot(r) {
makeroot(v)
access(r)
splay(r)
w_node := tr[r].min_node
w := tr[w_node].val
if w < v {
u1, u2 := eu[w_node], ev[w_node]
cut(u1, w_node)
cut(u2, w_node)
edge_idx++
tr[edge_idx].val = v
eu[edge_idx] = v
ev[edge_idx] = r
pushup(edge_idx)
link(v, edge_idx)
link(r, edge_idx)
}
if w < v {
if w > L_cycle {
L_cycle = w
}
} else {
if v > L_cycle {
L_cycle = v
}
}
} else {
edge_idx++
tr[edge_idx].val = v
eu[edge_idx] = v
ev[edge_idx] = r
pushup(edge_idx)
link(v, edge_idx)
link(r, edge_idx)
}
}
}
}
ql, qr := L_cycle+1, r
if ql <= qr {
min_val, count := query(1, 1, V, ql, qr)
if min_val == 1 {
ans += int64(count)
}
}
}
fmt.Println(ans)
}
```