package main
import (
"bufio"
"fmt"
"os"
"strconv"
)
func main() {
scanner := bufio.NewScanner(os.Stdin)
scanner.Split(bufio.ScanWords)
buf := make([]byte, 1024*1024)
scanner.Buffer(buf, 10*1024*1024)
readInt := func() int {
scanner.Scan()
val, _ := strconv.Atoi(scanner.Text())
return val
}
t := readInt()
out := bufio.NewWriter(os.Stdout)
defer out.Flush()
for tc := 0; tc < t; tc++ {
n := readInt()
m := readInt()
A := make([]int, n*m)
for i := 0; i < n*m; i++ {
A[i] = readInt()
}
B := make([]int, n*m)
posB := make([]int, 2*n*m+1)
for i := range posB {
posB[i] = -1
}
for i := 0; i < n*m; i++ {
B[i] = readInt()
posB[B[i]] = i
}
L := 0
for L < n*m {
p := posB[A[L]]
if p != -1 {
if L == 0 || p > posB[A[L-1]] {
L++
} else {
break
}
} else {
break
}
}
check := func(K int) bool {
isRet := make([]bool, n*m)
for i := 0; i < K; i++ {
isRet[posB[A[i]]] = true
}
c := 0
for j := 0; j < n*m; j++ {
if !isRet[j] {
if c > (j/m)*m {
return false
}
} else {
c++
}
}
return true
}
ansK := 0
low := 0
high := L
for low <= high {
mid := (low + high) / 2
if check(mid) {
ansK = mid
low = mid + 1
} else {
high = mid - 1
}
}
isRet := make([]bool, n*m)
for i := 0; i < ansK; i++ {
isRet[posB[A[i]]] = true
}
Ij := make([]int, 0, n*m-ansK)
for j := 0; j < n*m; j++ {
if !isRet[j] {
Ij = append(Ij, j)
}
}
numI := len(Ij)
fmt.Fprintln(out, numI)
if numI > 0 {
type Operation struct {
i int
x int
}
ansOps := make([]Operation, numI)
tree := make([]int, numI+1)
for i := 1; i <= numI; i++ {
tree[i] += 1
nxt := i + (i & -i)
if nxt <= numI {
tree[nxt] += tree[i]
}
}
for i := numI - 1; i >= 0; i-- {
j := Ij[i]
pi := i - (j % m)
idx := 0
rem := pi
for step := 19; step >= 0; step-- {
next := idx + (1 << step)
if next <= numI && tree[next] <= rem {
idx = next
rem -= tree[next]
}
}
pos := idx + 1
for k := pos; k <= numI; k += k & -k {
tree[k] -= 1
}
ansOps[pos-1] = Operation{
i: j/m + 1,
x: B[j],
}
}
for i := 0; i < numI; i++ {
fmt.Fprintln(out, ansOps[i].i, ansOps[i].x)
}
}
}
}