package main
import (
"io"
"os"
"strconv"
)
type FastScanner struct {
data []byte
idx int
}
func (fs *FastScanner) NextInt() int {
n := len(fs.data)
for fs.idx < n && (fs.data[fs.idx] < '0' || fs.data[fs.idx] > '9') {
fs.idx++
}
val := 0
for fs.idx < n {
c := fs.data[fs.idx]
if c < '0' || c > '9' {
break
}
val = val*10 + int(c-'0')
fs.idx++
}
return val
}
type Node struct {
cnt int32
lid [10]int32
rid [10]int32
lv [10]int32
rv [10]int32
}
var N int
func find(parent *[40]int, x int) int {
for parent[x] != x {
parent[x] = parent[parent[x]]
x = parent[x]
}
return x
}
func addMap(mp *[20]int, label int32, parent *[40]int, d *int) int {
idx := int(label)
if mp[idx] == -1 {
cur := *d
mp[idx] = cur
parent[cur] = cur
*d = cur + 1
}
return mp[idx]
}
func merge(a, b Node) Node {
var res Node
res.cnt = a.cnt + b.cnt
res.lv = a.lv
res.rv = b.rv
var mx, my [20]int
for i := 0; i < 20; i++ {
mx[i] = -1
my[i] = -1
}
var parent [40]int
d := 0
for i := 0; i < N; i++ {
addMap(&mx, a.lid[i], &parent, &d)
addMap(&mx, a.rid[i], &parent, &d)
addMap(&my, b.lid[i], &parent, &d)
addMap(&my, b.rid[i], &parent, &d)
}
for i := 0; i < N; i++ {
if a.rv[i] == b.lv[i] {
x := mx[int(a.rid[i])]
y := my[int(b.lid[i])]
rx := find(&parent, x)
ry := find(&parent, y)
if rx != ry {
parent[rx] = ry
res.cnt--
}
}
}
var rep [40]int
for i := 0; i < 40; i++ {
rep[i] = -1
}
next := 0
for i := 0; i < N; i++ {
rt := find(&parent, mx[int(a.lid[i])])
if rep[rt] == -1 {
rep[rt] = next
next++
}
res.lid[i] = int32(rep[rt])
}
for i := 0; i < N; i++ {
rt := find(&parent, my[int(b.rid[i])])
if rep[rt] == -1 {
rep[rt] = next
next++
}
res.rid[i] = int32(rep[rt])
}
return res
}
func query(tree []Node, size, l, r int) Node {
l += size
r += size + 1
var left, right Node
left.cnt = -1
right.cnt = -1
for l < r {
if l&1 == 1 {
if left.cnt == -1 {
left = tree[l]
} else {
left = merge(left, tree[l])
}
l++
}
if r&1 == 1 {
r--
if right.cnt == -1 {
right = tree[r]
} else {
right = merge(tree[r], right)
}
}
l >>= 1
r >>= 1
}
if left.cnt == -1 {
return right
}
if right.cnt == -1 {
return left
}
return merge(left, right)
}
func main() {
data, _ := io.ReadAll(os.Stdin)
fs := FastScanner{data: data}
n := fs.NextInt()
m := fs.NextInt()
q := fs.NextInt()
N = n
rows := make([][]int32, n)
for i := 0; i < n; i++ {
rows[i] = make([]int32, m)
for j := 0; j < m; j++ {
rows[i][j] = int32(fs.NextInt())
}
}
size := 1
for size < m {
size <<= 1
}
tree := make([]Node, size<<1)
for i := 0; i < size; i++ {
tree[size+i].cnt = -1
}
for col := 0; col < m; col++ {
var node Node
node.cnt = 1
for r := 0; r < n; r++ {
v := rows[r][col]
node.lv[r] = v
node.rv[r] = v
}
node.lid[0] = 0
node.rid[0] = 0
var lbl int32 = 0
for r := 1; r < n; r++ {
if node.lv[r] == node.lv[r-1] {
node.lid[r] = lbl
} else {
lbl++
node.lid[r] = lbl
node.cnt++
}
node.rid[r] = node.lid[r]
}
tree[size+col] = node
}
for i := size - 1; i >= 1; i-- {
left := tree[i<<1]
right := tree[i<<1|1]
if left.cnt == -1 {
tree[i] = right
} else if right.cnt == -1 {
tree[i] = left
} else {
tree[i] = merge(left, right)
}
}
out := make([]byte, 0, q*8)
for i := 0; i < q; i++ {
l := fs.NextInt() - 1
r := fs.NextInt() - 1
ans := query(tree, size, l, r)
out = strconv.AppendInt(out, int64(ans.cnt), 10)
out = append(out, '\n')
}
os.Stdout.Write(out)
}