using
System;
using
System.Collections.Generic;
class
Program
{
static
void
Solve(
long
r,
long
c, List<List<
long
>> grid)
{
var
pq =
new
PriorityQueue<Tuple<
long
, Tuple<
long
,
long
>>>(
Comparer<Tuple<
long
, Tuple<
long
,
long
>>>.Create((a, b) => b.Item1.CompareTo(a.Item1))
);
for
(
long
i = 0; i < r; i++)
{
for
(
long
j = 0; j < c; j++)
{
pq.Enqueue(
new
Tuple<
long
, Tuple<
long
,
long
>>(grid[(
int
)i][(
int
)j],
new
Tuple<
long
,
long
>(i, j)));
}
}
long
res = 0;
while
(pq.Count > 0)
{
long
height = pq.Peek().Item1;
long
i = pq.Peek().Item2.Item1;
long
j = pq.Peek().Item2.Item2;
pq.Dequeue();
if
(height != grid[(
int
)i][(
int
)j])
continue
;
if
(i == 0)
{
if
(i != r - 1)
{
if
(grid[(
int
)i + 1][(
int
)j] < height - 1)
{
res += height - 1 - grid[(
int
)i + 1][(
int
)j];
grid[(
int
)i + 1][(
int
)j] = height - 1;
pq.Enqueue(
new
Tuple<
long
, Tuple<
long
,
long
>>(height - 1,
new
Tuple<
long
,
long
>(i + 1, j)));
}
}
if
(j != 0)
{
if
(grid[(
int
)i][(
int
)j - 1] < height - 1)
{
res += height - 1 - grid[(
int
)i][(
int
)j - 1];
grid[(
int
)i][(
int
)j - 1] = height - 1;
pq.Enqueue(
new
Tuple<
long
, Tuple<
long
,
long
>>(height - 1,
new
Tuple<
long
,
long
>(i, j - 1)));
}
}
if
(j != c - 1)
{
if
(grid[(
int
)i][(
int
)j + 1] < height - 1)
{
res += height - 1 - grid[(
int
)i][(
int
)j + 1];
grid[(
int
)i][(
int
)j + 1] = height - 1;
pq.Enqueue(
new
Tuple<
long
, Tuple<
long
,
long
>>(height - 1,
new
Tuple<
long
,
long
>(i, j + 1)));
}
}
}
else
if
(i == r - 1)
{
if
(i != 0)
{
if
(grid[(
int
)i - 1][(
int
)j] < height - 1)
{
res += height - 1 - grid[(
int
)i - 1][(
int
)j];
grid[(
int
)i - 1][(
int
)j] = height - 1;
pq.Enqueue(
new
Tuple<
long
, Tuple<
long
,
long
>>(height - 1,
new
Tuple<
long
,
long
>(i - 1, j)));
}
}
if
(j != 0)
{
if
(grid[(
int
)i][(
int
)j - 1] < height - 1)
{
res += height - 1 - grid[(
int
)i][(
int
)j - 1];
grid[(
int
)i][(
int
)j - 1] = height - 1;
pq.Enqueue(
new
Tuple<
long
, Tuple<
long
,
long
>>(height - 1,
new
Tuple<
long
,
long
>(i, j - 1)));
}
}
if
(j != c - 1)
{
if
(grid[(
int
)i][(
int
)j + 1] < height - 1)
{
res += height - 1 - grid[(
int
)i][(
int
)j + 1];
grid[(
int
)i][(
int
)j + 1] = height - 1;
pq.Enqueue(
new
Tuple<
long
, Tuple<
long
,
long
>>(height - 1,
new
Tuple<
long
,
long
>(i, j + 1)));
}
}
}
else
{
if
(grid[(
int
)i + 1][(
int
)j] < height - 1)
{
res += height - 1 - grid[(
int
)i + 1][(
int
)j];
grid[(
int
)i + 1][(
int
)j] = height - 1;
pq.Enqueue(
new
Tuple<
long
, Tuple<
long
,
long
>>(height - 1,
new
Tuple<
long
,
long
>(i + 1, j)));
}
if
(grid[(
int
)i - 1][(
int
)j] < height - 1)
{
res += height - 1 - grid[(
int
)i - 1][(
int
)j];
grid[(
int
)i - 1][(
int
)j] = height - 1;
pq.Enqueue(
new
Tuple<
long
, Tuple<
long
,
long
>>(height - 1,
new
Tuple<
long
,
long
>(i - 1, j)));
}
if
(j != 0)
{
if
(grid[(
int
)i][(
int
)j - 1] < height - 1)
{
res += height - 1 - grid[(
int
)i][(
int
)j - 1];
grid[(
int
)i][(
int
)j - 1] = height - 1;
pq.Enqueue(
new
Tuple<
long
, Tuple<
long
,
long
>>(height - 1,
new
Tuple<
long
,
long
>(i, j - 1)));
}
}
if
(j != c - 1)
{
if
(grid[(
int
)i][(
int
)j + 1] < height - 1)
{
res += height - 1 - grid[(
int
)i][(
int
)j + 1];
grid[(
int
)i][(
int
)j + 1] = height - 1;
pq.Enqueue(
new
Tuple<
long
, Tuple<
long
,
long
>>(height - 1,
new
Tuple<
long
,
long
>(i, j + 1)));
}
}
}
}
Console.WriteLine(res);
}
static
void
Main()
{
long
r = 4, c = 5;
var
grid =
new
List<List<
long
>>
{
new
List<
long
> {1, 0, 5, 4, 2},
new
List<
long
> {1, 5, 6, 4, 8},
new
List<
long
> {2, 3, 4, 2, 1},
new
List<
long
> {2, 3, 4, 9, 8}
};
Solve(r, c, grid);
}
}
public
class
PriorityQueue<T>
{
private
readonly
List<T> heap;
private
readonly
IComparer<T> comparer;
public
PriorityQueue() :
this
(
null
) { }
public
PriorityQueue(IComparer<T> comparer) :
this
(16, comparer) { }
public
PriorityQueue(
int
capacity, IComparer<T> comparer)
{
this
.heap =
new
List<T>(capacity);
this
.comparer = comparer ?? Comparer<T>.Default;
}
public
void
Enqueue(T item)
{
heap.Add(item);
int
i = Count - 1;
while
(i > 0)
{
int
parent = (i - 1) / 2;
if
(comparer.Compare(heap[parent], item) <= 0)
break
;
heap[i] = heap[parent];
i = parent;
}
heap[i] = item;
}
public
T Dequeue()
{
T target = heap[0];
T root = heap[Count - 1];
heap.RemoveAt(Count - 1);
if
(Count > 0)
{
int
i = 0;
while
(i * 2 + 1 < Count)
{
int
leftChild = i * 2 + 1;
int
rightChild = i * 2 + 2;
int
swap = leftChild;
if
(rightChild < Count && comparer.Compare(heap[leftChild], heap[rightChild]) > 0)
swap = rightChild;
if
(comparer.Compare(heap[swap], root) >= 0)
break
;
heap[i] = heap[swap];
i = swap;
}
heap[i] = root;
}
return
target;
}
public
T Peek()
{
if
(Count == 0)
throw
new
InvalidOperationException(
"PriorityQueue is empty"
);
return
heap[0];
}
public
int
Count {
get
{
return
heap.Count; } }
}